Forward at most four emit arguments through EventEmitter method values

The dispatch instantiates one bridged emit per argument count and emitter
class; capping it at four keeps programs that only read emitter members
through computed keys from growing by the full table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Malte Ubl
2026-10-20 18:22:43 -07:00
co-authored by Claude Opus 5.5
parent 0cf62ebecf
commit 3a27a92cb4
4 changed files with 4 additions and 4 deletions
@@ -6,7 +6,7 @@
Through an untyped value, `listeners()` and `rawListeners()` of an event with a listener that has typed parameters are unsupported, and `emit('error')` of an object that is not an Error with no `error` listener is unsupported.
Untyped `newListener` and `removeListener` listeners receive `undefined` in place of a listener registered with typed parameters.
An untyped `emit` on, or an untyped read of `emit` from, an instance of a class that overrides `emit` is unsupported.
Calling `EventEmitter.prototype.emit` as a function value on a compiled emitter with more than 16 arguments after the event name is unsupported.
Calling `EventEmitter.prototype.emit` as a function value on a compiled emitter with more than 4 arguments after the event name is unsupported.
Calling EventEmitter.prototype's methods with an instance of a compiled class that does not extend EventEmitter as the receiver throws a `TypeError`.
Through an untyped value, a stream's `emit` and listener-introspection methods read as `undefined`.
`events.once` accepts EventEmitter and stream instances with a literal event name and an optional object-literal `{ signal }`; a stream's `data` event, other options values, and EventTarget emitters are unsupported.
@@ -40,7 +40,7 @@ export const EMITTER_PROTOTYPE_METHODS: ReadonlySet<string> = new Set([
/** `emit` forwards this many arguments after the event name; a call with
* more fences. */
const EMIT_ARGUMENTS = 16;
const EMIT_ARGUMENTS = 4;
/** The runtime's SCR_EE_M_* order: each method's name and the argument
* counts its call forwards. Node's methods that look at
@@ -40,7 +40,7 @@ console.log(o.removeAllListeners.call(o, "c") === o, o.eventNames());
o.removeAllListeners.call(o);
console.log(o.eventNames());
o.on("many", (...args: unknown[]) => console.log("many:", args.length, args.join(",")));
console.log(emit("many", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
console.log(emit("many", 1, 2, 3, 4));
console.log(o.setMaxListeners.call(o, 3) === o, o.getMaxListeners.call(o));
// off through a detached method value
+1 -1
View File
@@ -38,7 +38,7 @@ const plain = new EventEmitter();
const emit = plain.emit;
plain.on("hi", (a, b, c) => console.log("hi", a, b, c));
console.log(emit.call(plain, "hi", 1, "two", [3]));
console.log(emit.call(plain, "hi", 1, 2, 3, 4, 5, 6, 7, 8, 9));
console.log(emit.call(plain, "hi", 1, 2, 3, 4));
const fn = () => console.log("never");
plain.once("x", fn);
const off = plain.off;