[Core] Fix `Variant::construct` of `Object`

Variant type was not updated correctly causing leaks in ref-counted
This commit is contained in:
A Thousand Ships 2024-04-02 15:49:56 +02:00
parent e343dbbcc1
commit 8f3e2c96eb
No known key found for this signature in database
GPG Key ID: 2033189A662F8BD7
5 changed files with 34 additions and 1 deletions

View File

@ -153,11 +153,14 @@ public:
class VariantConstructorObject { class VariantConstructorObject {
public: public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
VariantInternal::clear(&r_ret);
if (p_args[0]->get_type() == Variant::NIL) { if (p_args[0]->get_type() == Variant::NIL) {
VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret); VariantInternal::object_assign_null(&r_ret);
r_error.error = Callable::CallError::CALL_OK; r_error.error = Callable::CallError::CALL_OK;
} else if (p_args[0]->get_type() == Variant::OBJECT) { } else if (p_args[0]->get_type() == Variant::OBJECT) {
VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign(&r_ret, p_args[0]); VariantInternal::object_assign(&r_ret, p_args[0]);
r_error.error = Callable::CallError::CALL_OK; r_error.error = Callable::CallError::CALL_OK;
} else { } else {
@ -169,6 +172,7 @@ public:
static inline void validated_construct(Variant *r_ret, const Variant **p_args) { static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret); VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign(r_ret, p_args[0]); VariantInternal::object_assign(r_ret, p_args[0]);
} }
static void ptr_construct(void *base, const void **p_args) { static void ptr_construct(void *base, const void **p_args) {
@ -198,11 +202,13 @@ public:
} }
VariantInternal::clear(&r_ret); VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret); VariantInternal::object_assign_null(&r_ret);
} }
static inline void validated_construct(Variant *r_ret, const Variant **p_args) { static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret); VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign_null(r_ret); VariantInternal::object_assign_null(r_ret);
} }
static void ptr_construct(void *base, const void **p_args) { static void ptr_construct(void *base, const void **p_args) {

View File

@ -0,0 +1,9 @@
# https://github.com/godotengine/godot/issues/90086
class MyObj:
var obj: WeakRef
func test():
var obj_1 = MyObj.new()
var obj_2 = MyObj.new()
obj_1.obj = obj_2

View File

@ -0,0 +1,6 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/invalid_property_assignment.gd
>> 9
>> Invalid assignment of property or key 'obj' with value of type 'RefCounted (MyObj)' on a base object of type 'RefCounted (MyObj)'.

View File

@ -0,0 +1,11 @@
# https://github.com/godotengine/godot/issues/90086
class MyObj:
var obj : WeakRef
func test():
var obj_1 = MyObj.new()
var obj_2 = MyObj.new()
assert(obj_2.get_reference_count() == 1)
obj_1.set(&"obj", obj_2)
assert(obj_2.get_reference_count() == 1)

View File

@ -0,0 +1 @@
GDTEST_OK