Merge pull request #114328 from kleonc/node_duplicating_signal_source_node_fix

`CONNECT_APPEND_SOURCE_OBJECT` on signal emission
This commit is contained in:
Rémi Verschelde
2026-01-20 00:22:32 +01:00
6 changed files with 111 additions and 17 deletions
+68
View File
@@ -316,6 +316,29 @@ TEST_CASE("[Object] Absent name getter") {
"The returned value should equal nil variant.");
}
class SignalReceiver : public Object {
GDCLASS(SignalReceiver, Object);
public:
Vector<Variant> received_args;
void callback0() {
received_args = Vector<Variant>{};
}
void callback1(Variant p_arg1) {
received_args = Vector<Variant>{ p_arg1 };
}
void callback2(Variant p_arg1, Variant p_arg2) {
received_args = Vector<Variant>{ p_arg1, p_arg2 };
}
void callback3(Variant p_arg1, Variant p_arg2, Variant p_arg3) {
received_args = Vector<Variant>{ p_arg1, p_arg2, p_arg3 };
}
};
TEST_CASE("[Object] Signals") {
Object object;
@@ -455,6 +478,51 @@ TEST_CASE("[Object] Signals") {
object.get_all_signal_connections(&signal_connections);
CHECK(signal_connections.size() == 0);
}
SUBCASE("Connecting with CONNECT_APPEND_SOURCE_OBJECT flag") {
SignalReceiver target;
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback1), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal");
CHECK_EQ(target.received_args, Vector<Variant>{ &object });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback1));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", "emit_arg");
CHECK_EQ(target.received_args, Vector<Variant>{ "emit_arg", &object });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2).bind("bind_arg"), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal");
CHECK_EQ(target.received_args, Vector<Variant>{ &object, "bind_arg" });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback3).bind("bind_arg"), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", "emit_arg");
CHECK_EQ(target.received_args, Vector<Variant>{ "emit_arg", &object, "bind_arg" });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback3));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback3).bind(&object), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", &object);
CHECK_EQ(target.received_args, Vector<Variant>{ &object, &object, &object });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback3));
// Source should be appended regardless of unbinding.
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback1).unbind(1), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", "emit_arg");
CHECK_EQ(target.received_args, Vector<Variant>{ &object });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback1));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2).bind("bind_arg").unbind(1), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", "emit_arg");
CHECK_EQ(target.received_args, Vector<Variant>{ &object, "bind_arg" });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2));
object.connect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2).unbind(1).bind("bind_arg"), Object::CONNECT_APPEND_SOURCE_OBJECT);
object.emit_signal("my_custom_signal", "emit_arg");
CHECK_EQ(target.received_args, Vector<Variant>{ "emit_arg", &object });
object.disconnect("my_custom_signal", callable_mp(&target, &SignalReceiver::callback2));
}
}
class NotificationObjectSuperclass : public Object {