Standard library / events · on the one-page reference

events

Experimental — new this milestone, not yet covered by the conformance suite; manually smoke-tested only. Pure in-memory state, no syscalls, works identically on native and WebAssembly.

A statically-typed EventEmitter<T>, built the same way Map/Set are (a real, dedicated type, not a plain class). A practical subset of Node's events module, with one necessary departure: Node lets one emitter mix wildly different listener payload types across event names ('data' gets a Buffer, 'error' gets an Error) with no static checking at all. Lumen can't express that without reflection, so every event name on one EventEmitter<T> instance shares the same payload type T — event names are still real string keys, just constrained to one shared type. A program that genuinely needs different payload shapes creates two separate emitters (or wraps both shapes in one union/record T).

~3.5× faster than Node's native EventEmitter on a tight emit loop: 10M emit() calls to one listener, compiled with --release-fast, measured around 43ms versus Node 20's ~160ms for the equivalent loop. No hidden-class/property-lookup machinery to warm up (a native binary starts at full speed), and listener dispatch goes through a plain function-pointer call rather than V8's more general call machinery.

APINotes
new EventEmitter<T>()construct an emitter for payload type T
.on(name, listener)(string, (T) => void) → void — registers a listener
.once(name, listener)(string, (T) => void) → void — fires at most once, then is dropped
.emit(name, value)(string, T) → void — calls every listener for name, in registration order
.removeAllListeners(name?)(string?) → void — clears one name, or every name if omitted
.listenerCount(name)string → int
function onGreeting(msg: string): void {
  console.log(msg);
}

const emitter = new EventEmitter<string>();
emitter.on("greet", onGreeting);
emitter.emit("greet", "hello"); // hello
console.log(emitter.listenerCount("greet")); // 1

Not guaranteed-safe: adding or removing a listener for the same event name from inside one of that name's own listeners, while it's still being emitted. Straightforward use (register listeners up front, emit later) is unaffected.