Files
scriptc/tests/diagnostics/ee-emit-override.ts
Chris Tate e47ad23c0c Subclasses may override emit in the forwarding shape, monomorphized per event
- class C extends EventEmitter may re-declare emit(event: string, ...args: unknown[]): boolean when the rest parameter only forwards through super.emit(event, ...args) in the method's own body; the body lowers once per event name as the real hierarchy method emit:<event> (vtable participation, (this, ...tuple) => bool ABI), with event bound to the name and the forward lowered to the runtime emit — or to the nearest override ancestor's specialization, JS's super chain.
- Emit sites dispatch by the whole-program rule: receivers at-or-below an override call the specialization directly (virtually when a deeper override exists); receivers above every override route through an interned helper that instanceOf-tests the topmost override subtrees and falls through to the runtime emit, so plain EventEmitter bindings holding override instances still dispatch like Node.
- super.<member> over an emitter-rooted base now lowers through the emitter spoke with static dispatch (an override at-or-below the lexical class never answers a super call); registering 'newListener'/'removeListener' listeners fences while a comparable class overrides emit (the runtime fires meta events internally, past the override), and every other emitter member keeps the surface fence with the forwarding-shape rule spelled out for emit.
- Corpus 2604-2609 pin both backends against Node: the logging override with upcast dispatch, two-level override chains with literal super.emit, once/off/prepend ordering and handled errors under an override, the unhandled-'error' throw through an override, the filtering override, and an emitter-subclass job queue; the diagnostics snapshot pins the three fences.
2026-07-24 09:37:57 -05:00

32 lines
1018 B
TypeScript

// The emit-override fences: only the FORWARDING SHAPE lowers — a rest
// parameter doing anything else names the rule; the other EventEmitter
// members keep the surface fence; and meta-event registration fences
// while any comparable class overrides emit (the runtime fires meta
// events internally, past the override).
import { EventEmitter } from "node:events";
class Peeker extends EventEmitter {
emit(event: string, ...args: unknown[]): boolean {
console.log(args.length); // reads the rest parameter — not a forward
return super.emit(event, ...args);
}
}
class Wrapped extends EventEmitter {
on(event: string, listener: (...a: unknown[]) => void): this {
return super.on(event, listener);
}
}
class Fine extends EventEmitter {
emit(event: string, ...args: unknown[]): boolean {
return super.emit(event, ...args);
}
}
const f = new Fine();
f.on("newListener", (name: string) => console.log("meta", name));
f.emit("x");
console.log(new Peeker());
console.log(new Wrapped());