When indexing a property on an Instance that returns an RBXScriptSignal, instead of returning a cached copy of the same object, it returns a new object for every time the property is indexed.
This creates issues when storing them inside tables as keys, as it means it can never be retrieved again using the t[k] syntax. They can be metamethod equated between each other, though this is very expensive. rawequal which compares objects by skipping any __eq magic, they are different.
This code sample demonstrates the issue pretty easily:
local t = {}
for i = 1, 5 do
t[game.Loaded] = true
end
print(t)
Instead of printing one key in the table, it prints 5 RBXScriptSignal objects at different memory locations, even though its the same signal.
This can also be an entry point to a very easy memory leak to developers who aren’t aware of this weird behaviour.
Expected behavior
When indexing a property that emits RBXScriptSignal, for example, BindableEvent.Event, it should return the same RBXScriptSignal object, instead of making a new one every index.
For various reasons (related to how engine objects are marshalled into the Luau VM), this is a difficult problem to solve. In fact there might be some edge cases that are even more difficult to handle than the general case.
We don’t consider the current behavior a bug. However, I can see why it is surprising and perhaps less than ideal to use.
I am going to close this as “By Design” since we don’t consider the current behavior a defect. However you can make a feature request that we change the behavior (assuming that is practical/possible after more investigation).
When we push a reference to a C++ object into the Luau VM we create a “userdata” object which wraps a reference to the C++ object. Luau tables treat the pointer to the “userdata” object as the key when they are inserted into Luau tables. So each new instance of a userdata object ends up being treated as a unique key. That is why the userdata objects create duplicate entries in a Luau table even if they internally refer to the C++ object.