Very odd behavior results when plugins interact with BindableFunctions

Steps to reproduce:
[ul]
[li]Create a BindableFunction[/li]
[li]Have a script in the level assign the OnInvoke handler[/li]
[li]Have a plugin currently running call the bindable with Invoke()[/li]
[li]The value returned from the Invoke() call is… a coroutine object?? (regardless of what value was returned by the OnInvoke handler)[/li]
[/ul]

Example code here (put it in a plugin. The example is attempting to get a reference to a script’s _G environment from the command line for debugging purposes):

-- Script side _G transferer shim implementation.
local ServerScriptService = game:GetService('ServerScriptService')

-- BindableFunction to transfer the _G reference through
local shim = Instance.new('BindableFunction', ServerScriptService)
shim.Name = 'GSHIM'
shim.Archivable = false

-- Script on the engine side to handle the request
local shimScript = Instance.new('Script', ServerScriptService)
shimScript.Name = 'GSHIM_Script'
shimScript.Archivable = false

-- Modify and run the script that sets up the OnInvoke
shimScript.Disabled = true
shimScript.Source = [[
game:GetService('ServerScriptService').GSHIM.OnInvoke = function()
	--> This function never ends up being correctly returned
	-- for some reason.
	local helperFunc = function()
		print("Helper function returning:", _G)
		return _G
	end
	print("Invoke returning value (helper function):", helperFunc)
	return helperFunc
end
]]
shimScript.Disabled = false

-- Pull the _G reference into the command line env using an 
-- intermediary helper function to avoid selialization.
print("Doing invoke")
local helper = shim:Invoke()
print("Done invoke")
print("Got (should be helper function):", helper)

-- Doesn't work, because helper is... a coroutine object 
-- somehow?? (Instead of the function I returned in the
-- OnInvoke above.)
_G._E = helper()
1 Like