Skip to content

Instantly share code, notes, and snippets.

@stravant
Last active January 27, 2025 13:42
Show Gist options
  • Save stravant/8820ed7386bd1f9264396f61fc851e3d to your computer and use it in GitHub Desktop.
Save stravant/8820ed7386bd1f9264396f61fc851e3d to your computer and use it in GitHub Desktop.
An implementation of RBXScriptSignal based on a wrapper around a BindableEvent
--------------------------------------------------------------------------------
-- Argument By-Reference Signal Wrapper --
-- This is a signal class implemented by wrapping a BindableEvent, which --
-- passes the event arguments by reference instead of by value, and which --
-- still works corectly even with SignalBehavior = deferred. --
--------------------------------------------------------------------------------
local Signal = {}
Signal.__index = Signal
function Signal.new()
local instance = Instance.new("BindableEvent")
local argsStorage = {}
-- Initial connection which will free the args list after all of the other
-- handlers (which must be called first because handlers are called in reverse
-- order of connection) have run already.
instance.Event:Connect(function(argCount, ref)
argsStorage[ref] = nil
end)
return setmetatable({
_inst = instance,
-- Must use a separate table for argsStorage so that there's no reference
-- back from argsStorage to instance, which would cause a memory leak.
_args = argsStorage,
_event = instance.Event,
}, Signal)
end
function Signal:Connect(fn)
return self._event:Connect(function(argCount, ref)
fn(unpack(self._args[ref], 1, argCount))
end)
end
function Signal:DisconnectAll()
self._inst:Destroy()
local instance = Instance.new("BindableEvent")
local argsStorage = {}
instance.Event:Connect(function(argCount, ref)
argsStorage[ref] = nil
end)
self._inst = instance
self._args = argsStorage
self._event = instance.Event
end
function Signal:Fire(...)
local args = {...}
local argCount = #args
-- Abuse the fact that function refs can be passed through BindableEvents intact
local ref = function() end
self._args[ref] = args
self._inst:Fire(argCount, ref)
end
function Signal:Wait()
local argCount, ref = self._event:Wait()
return unpack(self._args[ref], 1, argCount)
end
function Signal:Once(fn)
return self._event:ConnectOnce(function(argCount, ref)
fn(unpack(self._args[ref], 1, argCount))
end)
end
return Signal
@bardium
Copy link

bardium commented Jan 27, 2025

local ref = function() end currently only works with --!optimize 0 due to optimizations

consider replacing with this: local ref = coroutine.wrap(function() end)

@w-a-e aint no way way looking at RobloxSignal on Christmas
bro go back to exploiting or smth you dirty v3rmillion exploiter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment