Skip to content

fix(events): errorMonitor in the linked EventEmitter twin + handle-band guards (#4633)#5058

Merged
proggeramlug merged 3 commits into
mainfrom
fix/events-meta-parity
Jun 13, 2026
Merged

fix(events): errorMonitor in the linked EventEmitter twin + handle-band guards (#4633)#5058
proggeramlug merged 3 commits into
mainfrom
fix/events-meta-parity

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Fixes #4633.

Status of the issue's 12 failures

Most had been fixed by intervening work — on current main the events module was already at 67/69 (newListener/removeListener, rawListeners once-wrappers, listenerCount(event, listener), setMaxListeners validation, module-helper target validation: all passing). Two real failures remained; this PR fixes both → 69/69 (100%).

Fix 1 — errors/error-monitor

Three EventEmitter implementations exist (perry-stdlib events.rs, perry-runtime stream-emitter, perry-ext-events). The stdlib twin implements events.errorMonitor; instrumentation proved the twin that actually links into compiled binaries (even under PERRY_NO_AUTO_OPTIMIZE=1) is perry-ext-events — which had no monitor support. Ported dispatch_error_monitor into ext-events' emit/emit0: monitor listeners observe every 'error' emit before the regular listeners, once-wrappers prune, and the monitor never counts as handling (unhandled 'error' still throws).

Fix 2 — on/async-iterator-abort (SIGSEGV)

events.on(emitter, name, { signal }) validates its target by probing predicates with the raw EventEmitter handle (an id in the 0x38000..0x40000 band). is_event_target (event_target.rs) and object_ptr_from_value (node_stream_readwrite.rs) used 0x10000 floors, so the handle flowed through to a GcHeader read at handle-8 → unmapped memory. Raised both floors to the runtime-wide < 0x100000 handle convention (lldb-verified at both faults: EXC_BAD_ACCESS addr=0x37ff8).

Validation

  • ./run_parity_tests.sh --suite node-suite --module events: 67/69 → 69/69, no compile fails.
  • Blast-radius check on the floor change: full --module stream sweep — all 10 failures it reports reproduce identically on a pristine-main binary (4 known subclass/extends-* + 6 readable/pipe cases), i.e. 0 regressions.
  • cargo test -p perry-ext-events (8/8), runtime event tests (15/15).
  • Residual: the process-exit hang after a signal abort is pre-existing across the events abort family (the long-passing once/abort-cleans-pending-error hangs identically) — filed as events.once/events.on with AbortSignal: process never exits after completion (event loop parks on a leaked keepalive) #5056.

Code-only PR — version bump + changelog left for merge time.

Ralph Küpper added 3 commits June 13, 2026 02:11
…nd guards (#4633)

Brings node-suite/events parity from 67/69 to 69/69. The issue's 12
listed failures had mostly been fixed by intervening work; two remained:

1. errors/error-monitor: the perry-stdlib events twin implements
   events.errorMonitor dispatch, but the implementation that actually
   links into compiled binaries is perry-ext-events — which had none.
   Port dispatch_error_monitor (monitor listeners observe every 'error'
   emit before regular listeners, never count as handling) into
   ext-events' emit and emit0.

2. on/async-iterator-abort: SIGSEGV. events.on(emitter, name,
   { signal }) target validation passed the EventEmitter HANDLE
   (0x38000..0x40000 band) into is_event_target and
   object_ptr_from_value, whose 0x10000 floors let it through to the
   GcHeader probe at handle-8 — unmapped memory. Raise both floors to
   the runtime-wide 0x100000 handle boundary.

The post-fix test output matches Node; the remaining process-exit hang
after signal abort is pre-existing across the events abort family and
filed as #5056.
@proggeramlug proggeramlug merged commit 92b274e into main Jun 13, 2026
13 checks passed
@proggeramlug proggeramlug deleted the fix/events-meta-parity branch June 13, 2026 04:23
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.

node:events EventEmitter meta-events and max-listener validation diverge from Node

1 participant