--!strict local Promise = require "./Promise" local Spawn = require "./Spawn" type SignalNode = { Next: SignalNode?, Callback: (T...) -> (), } export type Signal = { Root: SignalNode?, Connect: (self: Signal, Callback: (T...) -> ()) -> () -> (), Wait: (self: Signal) -> Promise.Promise, Fire: (self: Signal, T...) -> (), DisconnectAll: (self: Signal) -> (), } local Signal = {} Signal.__index = Signal function Signal.new(): Signal return setmetatable({ Root = nil, }, Signal) :: any end function Signal.Connect(self: Signal, Callback: (T...) -> ()): () -> () local Node = { Next = self.Root, Callback = Callback, } self.Root = Node return function() if self.Root == Node then self.Root = Node.Next else local Current = self.Root while Current do if Current.Next == Node then Current.Next = Node.Next break end Current = Current.Next end end end end function Signal.Wait(self: Signal): Promise.Promise return Promise.new(function(Resolve) local Disconnect Disconnect = self:Connect(function(...) Disconnect() Resolve(... :: any) end) end) end function Signal.Fire(self: Signal, ...: T...) local Current = self.Root while Current do Spawn(Current.Callback, ...) Current = Current.Next end end function Signal.DisconnectAll(self: Signal) self.Root = nil end return Signal