Skip to content

feat(atoms): bundle custom events with change/mutate through MappedSignals#357

Merged
bowheart merged 3 commits intomasterfrom
josh/mapped-signal-event-group-forwarding
Mar 5, 2026
Merged

feat(atoms): bundle custom events with change/mutate through MappedSignals#357
bowheart merged 3 commits intomasterfrom
josh/mapped-signal-event-group-forwarding

Conversation

@bowheart
Copy link
Collaborator

@bowheart bowheart commented Mar 5, 2026

Summary

  • Custom events dispatched alongside signal.set() or signal.mutate() now stay bundled with the change (and mutate) event when propagating through MappedSignal layers
  • Previously, listeners at each MappedSignal layer received two separate callbacks — one for custom events, one for change/mutate. Now they receive a single unified event map
  • Standalone .send() events (no state change) are still forwarded immediately as before
  • Works recursively through any depth of signal/atom/MappedSignal composition

This also fixes a state tearing bug where mapped signals passed events dispatched along with .set and .mutate calls of inner signals to downstream listeners too early. Those listeners then ran before the inner update had fully propagated through the signal graph. That means those listeners would have to access the inner signal directly to read its current state since the outer signals that the listener is registered on don't have it yet. Deferring the passing along of those inner events in mapped signals prevents this bug completely.

Test plan

  • 34 new tests covering single-signal wrapping, map-mode, 2/3/5-deep nesting, mixed-mode nesting, multiple custom events, payload integrity, no-double-notification, and edge cases
  • All 142 pre-existing related tests pass (mapped-signal-events, mapped-signals, events, signals, proxies)
  • Full test suite passes (610/610 tests across 65 suites)

🤖 Generated with Claude Code

bowheart and others added 3 commits March 5, 2026 11:58
…gnals

Previously, custom events dispatched alongside signal.set() or
signal.mutate() were separated from the change/mutate events when
propagating through MappedSignal layers. Listeners received two
separate callbacks instead of one unified event map.

Now, non-mutate custom events from inner signal state changes are
buffered in MappedSignal.r() and included alongside change/mutate
events when MappedSignal.j() runs, keeping all events together in
one event map at every layer of composition. Standalone events via
.send() (no state change) are still forwarded immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 9 tests verifying standalone .send() events propagate through
2/3/4/5 layers of nested MappedSignals, covering single-signal mode,
map-mode, mixed nesting, object map sends, payload integrity, no
change event leakage, and no double-notification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bowheart bowheart merged commit d49d608 into master Mar 5, 2026
2 checks passed
@bowheart bowheart deleted the josh/mapped-signal-event-group-forwarding branch March 5, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant