local userdata = newproxy(true)
local bindableEvent = Instance.new("BindableEvent")
bindableEvent.Event:Connect(function(...)
print("Fired with args:", ...) -- Prints "Hello" nil
end)
bindableEvent:Fire("Hello", userdata)
Expected Behavior
Passing a userdata created by newproxy() through a BindableEvent:Fire() should allow me to receive it as an argument in .Event:Connect()
Actual Behavior
Passing the result of newproxy() through :Fire() results in a nil argument when received through :Connect()
Workaround
The current workaround is just using a standard empty Lua table instead.
Issue Area: Engine Issue Type: Other Impact: Low Frequency: Constantly Date First Experienced: 2023-02-20 00:02:00 (-06:00) Date Last Experienced: 2023-02-20 04:02:00 (-06:00)
Only Roblox userdata objects are allowed in arguments to events, as described in “Parameter Limitations” at BindableEvent | Roblox Creator Documentation
Maybe it could’ve been more explicit to say that userdata created in Luau isn’t allowed.
The parameter limitations described in the website seems to direct it’s focus to RemoteEvent and RemoteFunction:
Any type of Roblox object such as an Enum, Instance, or userdata can be passed as a parameter when a RemoteEvent is fired or a RemoteFunction invoked. Lua types such as numbers, strings, and booleans can also be passed, although there are some limitations on how data can be passed.
I also noticed that coroutines cannot be passed to it. It’s crazy how I didn’t know about this until now.
Why do BindableEvents/BindableFunctions have these behaviors?
It is clear that you are not doing anything related to network with these two objects.
There is no need to create full new tables when passing one.
Custom userdatas and coroutines should be passed with no problems, don’t understand why they are excluded.
They still have the bug where if you use coroutine.resume to resume the current yielding thread it makes the thread who called Invoke wait forever even though the callback finished and even returned. (This issue can be solved by using task.spawn, but why?)
My only guesses for the first three points is that because they are used for communication between CoreScripts and Normal Scripts sometimes, Roblox decided to have these points as a feature to avoid filtering on the CoreScript side which is written in Luau.
My second guess is that engine does this for an unknown reason that I want to know…
The bug of the fourth point is shown here as code form:
I believe the documentation here should be “Only Roblox objects are allowed, Lua userdata objects created through newproxy are not allowed”
Feel free to rework the wording on that.
To @focasds : The mutation behaviour with tables actually happens because bindables can cross what I like to refer to as “VM stacks” (game script, corescript, plugins, so on), there be dragons with letting two or more memory isolated stacks access the same table