Skip to content

core modules: bare specifier events resolves to a stub EventEmitter (empty prototype, no setMaxListeners/on/emit) — node:events works; blocks signal-exit → ink #4995

@proggeramlug

Description

@proggeramlug

Summary

The bare core specifier 'events' (no node: prefix) resolves to a broken EventEmitter whose instances have an empty prototypesetMaxListeners, on, once, emit, removeListener, etc. are all undefined. The node:-prefixed form 'node:events' resolves to the correct, full EventEmitter. 'events' and 'node:events' must be the same builtin.

This is the next ink wall (the #4993 process fix let init proceed into signal-exit, which does require('events')).

Evidence (same binary, post-#4993)

import { EventEmitter } from 'node:events':
    new EventEmitter().setMaxListeners = function   ✓   (.on/.emit/.once/.removeListener all function)
    setMaxListeners(Infinity) → OK

import EE from 'events':                 // bare specifier
    typeof EE = function
    new EE().setMaxListeners = undefined            ✗
    new EE().on             = undefined            ✗
    → TypeError: setMaxListeners is not a function

import * as ev from 'events':
    ev.EventEmitter = function, ev.default = function
    new ev.EventEmitter().setMaxListeners = undefined   ✗

So bare 'events' yields a constructor (typeof function) but its new instances carry no prototype methods, whereas 'node:events' yields the complete class. Same for require('events') (the CJS form most older packages use).

Minimal repro

import EE from 'events';
console.log(typeof new EE().setMaxListeners);          // Perry: undefined  ✗
import { EventEmitter } from 'node:events';
console.log(typeof new EventEmitter().setMaxListeners); // Perry: function   ✓

Node: both function.

How it surfaced (ink, #348)

signal-exit/index.js (transitive via cli-cursorrestore-cursor) runs at init:

var EE = require('events');
if (typeof EE !== 'function') EE = EE.EventEmitter;
emitter = process.__signal_exit_emitter__ = new EE();
...
emitter.setMaxListeners(Infinity);   // → TypeError: setMaxListeners is not a function

Because require('events') returns the stub EventEmitter, new EE() has no setMaxListeners, throwing during module init — before any user code.

Scope / suggested fix

Impact

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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