summaryrefslogtreecommitdiff
path: root/core/object
diff options
context:
space:
mode:
authorK. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>2022-06-27 13:10:04 -0700
committerK. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>2022-06-27 13:33:06 -0700
commit9ddebc0c22866d6b7a7ff3fa64b67cc86c8664da (patch)
tree3bb41cb3143f197ca53ee93f7375598ef5886ec6 /core/object
parentc41e4b10c3317f837d4b3ece2fb725a8067d884b (diff)
Add a const call mode to Object, Variant and Script.
For this to work safely (user not call queue_free or something in the expression), a const call mode was added to Object and Variant (and optionally Script). This mode ensures only const functions can be called, making it safe to use from the editor. Co-Authored-By: reduz <reduzio@gmail.com>
Diffstat (limited to 'core/object')
-rw-r--r--core/object/object.cpp49
-rw-r--r--core/object/object.h2
-rw-r--r--core/object/script_language.cpp5
-rw-r--r--core/object/script_language.h1
4 files changed, 57 insertions, 0 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 6585c3fa79..440da00c17 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -669,6 +669,7 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
+ case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
return ret;
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
}
@@ -688,6 +689,54 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_
return ret;
}
+Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+ if (p_method == CoreStringNames::get_singleton()->_free) {
+ // Free is not const, so fail.
+ r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST;
+ return Variant();
+ }
+
+ Variant ret;
+ OBJ_DEBUG_LOCK
+
+ if (script_instance) {
+ ret = script_instance->call_const(p_method, p_args, p_argcount, r_error);
+ //force jumptable
+ switch (r_error.error) {
+ case Callable::CallError::CALL_OK:
+ return ret;
+ case Callable::CallError::CALL_ERROR_INVALID_METHOD:
+ break;
+ case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
+ break;
+ case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
+ case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
+ case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
+ return ret;
+ case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
+ }
+ }
+ }
+
+ //extension does not need this, because all methods are registered in MethodBind
+
+ MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
+
+ if (method) {
+ if (!method->is_const()) {
+ r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST;
+ return ret;
+ }
+ ret = method->call(this, p_args, p_argcount, r_error);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ }
+
+ return ret;
+}
+
void Object::notification(int p_notification, bool p_reversed) {
_notificationv(p_notification, p_reversed);
diff --git a/core/object/object.h b/core/object/object.h
index 7dac96bc2b..e065634000 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -67,6 +67,7 @@ enum PropertyHint {
PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
+ PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
@@ -759,6 +760,7 @@ public:
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args);
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ virtual Variant call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
template <typename... VarArgs>
Variant call(const StringName &p_method, VarArgs... p_args) {
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 66c9a80193..4623d0e525 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -295,6 +295,11 @@ void ScriptServer::save_global_classes() {
}
////////////////////
+
+Variant ScriptInstance::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ return callp(p_method, p_args, p_argcount, r_error);
+}
+
void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state) {
List<PropertyInfo> pinfo;
get_property_list(&pinfo);
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 0a8e79a24e..776a9bfaab 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -190,6 +190,7 @@ public:
return callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
}
+ virtual Variant call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); // implement if language supports const functions
virtual void notification(int p_notification) = 0;
virtual String to_string(bool *r_valid) {
if (r_valid) {