diff options
author | K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com> | 2022-06-27 13:10:04 -0700 |
---|---|---|
committer | K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com> | 2022-06-27 13:33:06 -0700 |
commit | 9ddebc0c22866d6b7a7ff3fa64b67cc86c8664da (patch) | |
tree | 3bb41cb3143f197ca53ee93f7375598ef5886ec6 /core/object | |
parent | c41e4b10c3317f837d4b3ece2fb725a8067d884b (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.cpp | 49 | ||||
-rw-r--r-- | core/object/object.h | 2 | ||||
-rw-r--r-- | core/object/script_language.cpp | 5 | ||||
-rw-r--r-- | core/object/script_language.h | 1 |
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) { |