Skip to content

Changelog ​

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased] ​

2.3.2 - 2026-07-22 ​

Fixed ​

  • Fixed a regression in v2.3.x where immediate-mode disconnections did not stop the listener from being dispatched.

Changed ​

  • Improved performance when dispatching signals with no connections.

2.3.1 - 2026-07-21 ​

Removed ​

  • Removed the internal SIGNAL_BEHAVIOR flag that toggled task.spawn vs task.defer.
    • Flags are considered unstable and subject to change, this flag conflicted with internal dispatching and caused an infinite loop which froze the program when enabled.
    • The edge cases this was originally meant to address are now handled by deferred mutations, a much more comprehensive and performant mechanism — making the flag redundant.
    • This does not affect your ability to defer other operations (e.g. functions in listeners); only the internal spawn/defer toggle has been removed.

2.3.0 - 2026-07-21 ​

Changes since v2.2.0:

Changed ​

  • Maintenance: Refactored Types module. Shouldn't change type behavior in public APIs, but may improve inference speed.

  • Config: The default ERROR_INFO_MODE has been changed to "Full" (always prefer task.spawn) due to possible C-side issues with coroutine.resume.

    • You may opt back into a different mode if you require the additional performance and are aware of the risks.
  • Performance: Greatly improved non-yielding fire performance by switching to a more efficient dispatching technique with minimized thread resumptions.

    • Signals with only one connection may be slightly slower, but benefits should be visible with two or more connections.

    From internal benchmarking:

    Connection Count% Improvement from v2.2.0
    1-18.8% (Slower)
    2+49.2% (Faster)
    5+258.6% (Faster)
    10+535.1% (Faster)
    50+1523.2% (Faster)

Fixed ​

  • Fixed a missing type export for WrapConnection in the main module.

2.3.0-rc.1 - 2026-07-20 ​

Changed ​

  • Maintenance: Refactored Types module. Shouldn't change type behavior in public APIs, but may improve inference speed.

  • Config: The default ERROR_INFO_MODE has been changed to "Full" (always prefer task.spawn) due to possible C-side issues with coroutine.resume.

    • You may opt back into a different mode if you require the additional performance and are aware of the risks.
  • Performance: Greatly improved non-yielding fire performance by switching to a more efficient dispatching technique with minimized thread resumptions.

    • Signals with only one connection may be slightly slower, but benefits should be visible with two or more connections.

    From internal benchmarking:

    Connection Count% Improvement from v2.2.0
    1-18.8% (Slower)
    2+49.2% (Faster)
    5+258.6% (Faster)
    10+535.1% (Faster)
    50+1523.2% (Faster)

2.2.0 - 2026-07-17 ​

Changes since v2.1.7:

Fixed ​

  • Fixed a class of iterator invalidation edge cases involving connections made after immediate-mode 'Now' disconnections on the active node.
    • Note: Those who've not used deferred mutation opt-outs were not impacted.
  • Fixed an iterator invalidation edge case when DisconnectNow() was used on a tail connection before DisconnectAllNow().

Added ​

  • Added new method Signal:GetConnections(), which returns an array of active connections on the signal, ordered from oldest to newest.
  • Connection:DestroyNow() is now supported.

2.2.0-rc.2 - 2026-07-15 ​

Fixed ​

  • Fixed an iterator invalidation edge case when DisconnectNow() was used on a tail connection before DisconnectAllNow().

2.2.0-rc.1 - 2026-07-14 ​

Fixed ​

  • Fixed a class of iterator invalidation edge cases involving connections made after immediate-mode 'Now' disconnections on the active node.
    • Note: Those who've not used deferred mutation opt-outs were not impacted.

Added ​

  • Added new method Signal:GetConnections(), which returns an array of active connections on the signal, ordered from oldest to newest.
  • Connection:DestroyNow() is now supported.

2.1.7 - 2026-07-12 ​

Fixed ​

  • Changed the approach on how we handled the iterator invalidation bug where immediate-mode 'Now' connections made within Once connections were missed in the same dispatch cycle.
    • This fixes the behavior of FireNow in such cases.
  • Fixed the Connection type not having the default signature in the exported public type.

2.1.6 - 2026-07-12 [YANKED] ​

Fixed ​

  • Changed the approach on how the iterator invalidation bug was handled in previous release. FireNow should work as expected in such cases.
  • Fixed the Connection type not having the default signature in the exported public type.

2.1.5 - 2026-07-12 ​

Fixed ​

  • Fixed an edge-case iterator invalidation bug involving immediate-mode 'Now' connections made within Once connections.

2.1.4 - 2026-07-07 ​

Fixes ​

  • Uninstantiated generic from Signal.new() is now handled properly. Previously, the signature was not being sanitized in all cases.

2.1.3 - 2026-06-24 ​

Hello again, this release is mostly just some codebase maintenance and cleaning up.

Added ​

Changes ​

2.1.2 - 2026-06-03 ​

Fixes ​

Fixed wally installation once more, default.project.json wasn't getting included.

2.1.1 - 2026-06-02 ​

Fixes ​

Fix GenericSignal unintentionally still using UDTFs in Connection type with new GenericConnection type.

See the API Reference for usage information.

2.1.0 - 2026-05-31 ​

Back again with more improvements!

Additions ​

  • Added a new interface constructor Signal.wrap(RBXScriptSignal) and WrapSignal<RBXScriptSignal> type.

    • Signatures can be conveniently inferred from the given RBXScriptSignal when available. Example:
    lua
    local heartbeatEvent = Signal.wrap(game:GetService("RunService").Heartbeat)
    heartbeatEvent:Connect(function(deltaTime: number)
    	print(`deltaTime: {deltaTime}`)
    end)

Improvements ​

  • Signal:Wait() and Signal:WaitNow() can now be safely resumed externally without leaving the internal connection active.
  • Dead :Wait()s where the event resumed but the thread is not resumable no longer produces errors.
  • Improved the performance of dispatch in production by using coroutine.resume with an error and traceback logger, while keeping debugging benefits of task.spawn in Roblox Studio.
    • With this, USE_TASK_LIBRARY has been replaced with ERROR_INFO_MODE, which lets you decide between performance and error information, set to "Auto" by default.
  • Improve argument packing/unpacking performance.

Documentation ​

  • Rewrote much of the Introduction documentation page, with much more detailed comparisons between BindableEvents and other popular signal libraries.
  • Added the 'Future Considerations' documentation page, which goes over some notable Luau RFCs and how NamedSignal might evolve if they were implemented.
  • Minor cleanup across a few other documentation pages.

Other Changes ​

  • wally.toml has been moved back to the project root, the wally module will no longer appear in builds.
  • Minor internal refactoring.

2.0.4 - 2026-04-17 ​

Fix instance name and wally installation.

2.0.0 - 2026-04-16 ​

After much wait, NamedSignal v2.0.0 is here!

Major Changes ​

  • Deferred mutations have been completely reworked and is now much more comprehensive and completely yieldless (even Signal:Fire()!).
  • Added -Now suffixed method equivalents to most deferred APIs to bypass deferred mutations.

Minor Additions ​

  • Added Connection:Reconnect(), which reconnects the connection back to the end of the Signal.
  • Added the GenericSignal type, which uses pure generics instead of UDTFs to workaround unserializable types.

Removed APIs ​

  • Removed bypassReentrancy parameters from functions that had them in favor of the new -Now suffixed methods.

Other Changes ​

  • No longer a Class 3 Signal under Gohan's Certification, see my reasoning for doing so.
  • Documentation has been completely rewritten using VitePress, new benchmarks are still a work in progress.
  • Slightly improve the performance of non-yielding dispatch by implementing a "fast" cache as a local variable.

1.2.1 - 2026-02-11 ​

Removed monotonic connection counters, as they were no longer necessary with deferred mutations

1.2.0 - 2026-02-10 ​

Comply with GohanDucis Class 3 signal certification.

1.1.0 - 2026-02-09 ​

Prevent connections made during invocation from being fired (with minimal impact to performance).

1.0.0 - 2026-02-08 ​

Minor code cleanup and type improvements, add new benchmarks and wally install.

Bumped version to major 1 in accordance with Semantic Versioning 2.0,0, indicating public release and stability guarantee.

0.1.0 - 2026-02-07 ​

Initial release of NamedSignal