Skip to content

runtime: a subclass method overriding a native base method (EventEmitter.emit) is silently bypassed — override never runs #6316

Description

@proggeramlug

Summary

A user method that overrides a native base-class method is silently bypassed: the call dispatches straight to the native implementation and the override never runs. super.<method>() from inside such an override also doesn't reach the base.

Confirmed on a clean origin/main build (0960415ad).

Repro

import { EventEmitter } from "node:events";

class Bus extends EventEmitter {
  emit(ev: string, ...args: any[]): boolean {
    console.log("override ran:", ev);
    return super.emit(ev, ...args);
  }
}

const b = new Bus();
b.on("ping", (x: number) => console.log("listener got:", x));
console.log("emit returned:", b.emit("ping", 42));
output
node 26 override ran: ping / listener got: 42 / emit returned: true
perry main listener got: 42 / emit returned: true

The override ran: line is missingb.emit(...) went directly to the native EventEmitter.emit, skipping the user's method entirely. No error, no warning.

Why it matters

Subclassing EventEmitter and overriding emit/on to add logging, filtering, or instrumentation is an extremely common Node pattern. Today it silently does nothing, which is a wrong answer rather than a crash — the worst failure mode.

Scope

Surfaced while fixing #6301 (class X extends EventTarget inheriting nothing). That issue's fix routes EventTarget methods through the class chain and places them last on the lookup path so a subclass override wins. This issue is the mirror problem for native bases generally: the override is not consulted at all.

Two things to establish:

  1. Which native base classes are affected (EventEmitter confirmed; check EventTarget, Error, Array, Promise, stream classes).
  2. Whether the dispatch bypass and the super.<method>() failure are one root cause or two.

Note super.<method>() into a native base was independently observed as broken during #6301 and scoped out of that PR as orthogonal — this is its tracking issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions