Repository: godot
Issue: Free a node which has a running Tween or an awaited coroutine method will cause Memory leak
Labels: bug,topic:core

### Tested versions

- Reprocucible in 4.4.dev 4

### System information

Windows 11, Vulkan API 1.3.280 - Forward+ - Using Vulkan Device #0: NVIDIA - NVIDIA GeForce RTX 3060 Ti

### Issue description

If a Tween is running but free it's bound Node midway, will cause memory leak.
If await a Node's coroutine but free this node midway, will cause memory leak.

Here is an expample.
![屏幕截图 2024-11-18 170715](https://github.com/user-attachments/assets/2af99525-8802-4380-ac0f-c5282720c4d6)

A diff between two outputs of `get_all_objects_id` which needs a custom build of Godot:
![屏幕截图 2024-11-18 171739](https://github.com/user-attachments/assets/6abbcf3c-a49e-4f09-91eb-2b38403a2fbc)

In foo.tscn's script foo.gd:
```
extends Node2D

func test():
	printt("foo test 1")
	var tween = create_tween()
	tween.tween_interval(1)
	await tween.finished
	printt("foo test 2")
	return 1
```

In main.tscn's script main.gd:
```
extends Node2D

const FOO = preload("res://foo.tscn")

var result

func _ready() -> void:
	# Objects's count increasing at the speed of 1 Object / 5 seconds
	var tween = create_tween()
	tween.set_loops(-1)
	tween.tween_callback(go).set_delay(5)
	
	# Objects's count increasing at the speed of 3 Object / 5 seconds.
	#var tween = create_tween()
	#tween.set_loops(-1)
	#tween.tween_callback(go2).set_delay(5)
	
	# these codes print all objects id if you can compile a custom version Godot.
	# these codes can remain commented if you don't want to know what Object is leaking.
	#var tween2 = create_tween()
	#tween2.set_loops(-1)
	#tween2.tween_callback(get_all_objects_id).set_delay(5.5)

## can observe an increasing of Objects' count at a speed of 1 Object per 5 seconds.
## The leaking object is a Tween created by foo.
func go() -> void:
	var foo = FOO.instantiate()
	add_child(foo)
	
	# 0.5 second later, free foo to interrupt foo's awaiting.
	# can observe an increasing of Object's count.
	# Which cusing 1 Tween Object leaking.
	var tween = create_tween()
	tween.tween_callback(Callable(foo, "queue_free")).set_delay(0.5)
	
	# let foo to await a 1-second-timer's time out.
	foo.test()
	
## can observe an increasing of Objects' count at a speed of 3 Objects per 5 seconds.
## The leaking objects are 1 Tween created by foo and 2 GDScriptFunctionState.
func go2() -> void:
	var foo = FOO.instantiate()
	add_child(foo)
	
	# 0.5 second later, free foo to interrupt foo's awaiting.
	# can observe an increasing of Object's count.
	# Which cusing 1 Tween and 2 GDScriptFunctionState Objects leaking.
	var tween = create_tween()
	tween.tween_callback(Callable(foo, "queue_free")).set_delay(0.5)
	
	# let foo to await a 1-second-timer's time out
	result = await foo.test()
```

C++ modification if you want to know which object is leaking:
In object.h:
```
TypedArray<uint64_t> get_all_objects_id();
```

In object.cpp:
```
void Object::notify_property_list_changed() {
	emit_signal(CoreStringName(property_list_changed));
}

static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
	if (script_type.is_valid() && script_type->is_valid()) {
		return GDScript::debug_get_script_name(script_type);
	} else if (native_type != StringName()) {
		return native_type.operator String();
	} else {
		return Variant::get_type_name(builtin_type);
	}
}

static String _get_var_type(Object *p_var) {
	String basestr;

	bool was_freed;
	Object *bobj = p_var;
	
	if (bobj->is_class_ptr(GDScriptNativeClass::get_class_ptr_static())) {
		basestr = Object::cast_to<GDScriptNativeClass>(bobj)->get_name();
	} else {
		basestr = bobj->get_class();
		if (bobj->get_script_instance()) {
			basestr += " (" + GDScript::debug_get_script_name(bobj->get_script_instance()->get_script()) + ")";
		}
	}

	return basestr;
}

static TypedArray<uint64_t> all_objects_id;
static void _get_obj_id(Object *p_obj) {
	all_objects_id.push_back(p_obj->get_instance_id());
	String basestr = _get_var_type(p_obj);
	print_line("xxxx uitos:" + uitos(p_obj->get_instance_id()) + " " + " itos:" + itos(p_obj->get_instance_id()) + " " + basestr);
}

TypedArray<uint64_t> Object::get_all_objects_id() {
	all_objects_id.clear();
	ObjectDB::debug_objects(_get_obj_id);
	return all_objects_id;
}

void Object::_bind_methods() {
	ClassDB::bind_method(D_METHOD("get_all_objects_id"), &Object::get_all_objects_id);
```
![屏幕截图 2024-11-18 165943](https://github.com/user-attachments/assets/e51d21d2-d915-4c86-85a7-1f86e678c7db)


### Steps to reproduce

1. run MRP and see the figure of Monitor's Object count
2. comment 3-line of `tween_callback(go)` and uncomment 3-line of `tween_callback(go2)` and re-run.

### Minimal reproduction project (MRP)

[test_gdscriptfunctionstate.zip](https://github.com/user-attachments/files/17797845/test_gdscriptfunctionstate.zip)