mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
- 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.
32 lines
1018 B
TypeScript
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());
|