Currently, BindableEvent and BindableFunction objects will clone the shape of a table, but not inherit its metatable or memory location. This is ok behaviour if we’re sending the table to a different VM context (such as a CoreScript or Plugin), but if I’m operating within the same VM context, I’d expect the table to remain the same, keeping the metatable and memory location.
This creates extremely unusual behaviour when implementing events, and forces developers to use slower custom Signal implementations instead of RBXScriptSignals, since the bindable clones the table.
Repro script
local b = Instance.new("BindableEvent")
local t = {}
b.Event:Connect(function(d)
print(tostring(d))
end)
print(tostring(t))
b:Fire(t)
from main func - table: 0xc8b41d57eaa68ec6
from bindable - table: 0xc034b9d71d976b66
Expected behavior
The table object to be the same table when listening to a signalled bindable in the same context.
I want to add that the Legacy Chat System looks like it ran into this exact problem because it doesn’t send the objects within its events (so I dont know how it wasn’t fixed internally?), it sends an identifier to the object.
I know that system isn’t being maintained anymore, but I thought it was interesting to add nethertheless.
As a workaround, you can send your values wrapped in a function object (inside a single VM):
local b = Instance.new("BindableEvent")
local function wrap(t) return function() return t end end
local t = {}
b.Event:Connect(function(dwrap)
local d = dwrap()
print(tostring(d))
end)
print(tostring(t))
b:Fire(wrap(t))