1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-07 12:30:27 +00:00

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>
This commit is contained in:
K. S. Ernest (iFire) Lee
2022-06-27 13:10:04 -07:00
parent c41e4b10c3
commit 9ddebc0c22
23 changed files with 179 additions and 53 deletions

View File

@@ -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);