Files
scriptc/tests/corpus/5983-runtime-constructor.ts
T
Chris Tate 0b00ecfc23 Read x.constructor on EventEmitter and stream instances
`x.constructor` on a value typed as EventEmitter or a stream class
stopped at SC2020. The runtime now records each instance's Node class
name: fs streams as ReadStream and WriteStream, child process stdio as
Socket, worker stdio as ReadableWorkerStdio and WritableWorkerStdio, and
Hash/Hmac stream views as Hash and Hmac (zlib streams, the base classes
and program subclasses already did). The name is the one Node's leak
warning and argument-type errors print, so those messages now name the
same class as Node.

`x.constructor.name` reads that name (scr_emitter_class_name).
`x.constructor === C` for EventEmitter or a stream class tests the
instance's own class: C's interval, none of its direct subclasses', and
C's name, as fs, zlib, crypto, child process and worker streams share the
base classes' vtables. `x.constructor` as a value is the class object of
EventEmitter or the stream class the instance belongs to; for instances
of the other runtime classes and of program subclasses it reports SC1090
at run time.
2026-10-19 21:44:33 -05:00

49 lines
2.0 KiB
TypeScript

// x.constructor on instances of EventEmitter and the stream classes:
// .name is the class Node reports (fs, zlib and program subclasses
// included), === compares with the instance's own class, and the value
// is the class object for EventEmitter and the stream classes.
import { EventEmitter } from "node:events";
import { Duplex, PassThrough, Readable, Transform, Writable } from "node:stream";
import * as fs from "node:fs";
import * as zlib from "node:zlib";
class Bus extends EventEmitter {}
const emitter = new EventEmitter();
const bus: EventEmitter = new Bus();
console.log("emitter", emitter.constructor === EventEmitter, emitter.constructor.name);
console.log("subclass", bus.constructor === EventEmitter, bus.constructor.name);
const streams: Readable[] = [new Readable(), new Duplex(), new Transform(), new PassThrough()];
for (const s of streams) {
console.log(
"stream",
s.constructor.name,
s.constructor === Readable,
s.constructor === Duplex,
s.constructor === Transform,
s.constructor === PassThrough,
s.constructor !== Readable,
);
}
const from = Readable.from(["a"]);
console.log("from", from.constructor.name, from.constructor === Readable);
const readStream: Readable = fs.createReadStream(import.meta.filename);
const writeStream: Writable = fs.createWriteStream("/dev/null");
console.log("fs", readStream.constructor.name, readStream.constructor === Readable);
console.log("fs", writeStream.constructor.name, writeStream.constructor === Writable);
readStream.destroy();
writeStream.destroy();
const gzip: Transform = zlib.createGzip();
const inflate: Transform = zlib.createInflateRaw();
console.log("zlib", gzip.constructor.name, inflate.constructor.name, gzip.constructor === Transform);
const kinds: EventEmitter[] = [new EventEmitter(), new Writable(), new PassThrough()];
for (const k of kinds) {
const Kind = k.constructor as typeof EventEmitter;
console.log("value", Kind.name, Kind === EventEmitter, k instanceof Kind, new Kind() instanceof EventEmitter);
}