feat(util/stream): util.inherits + stream prototype scaffold (express unblocked)#984
Merged
Merged
Conversation
Express compile blocked at `util.inherits(SendStream, Stream)` because
`require('stream')` returned a null-proto namespace and `Stream.prototype`
was undefined. The V8-fallback `node:stream` shim is now a real `Stream`
class with sub-classes attached as static properties + `__perry_commonjs`
so `require()` returns the class itself; `util.inherits` now defines
`super_` and validates inputs.
- crates/perry-jsruntime/src/modules.rs: rewrite `node:stream` shim
around a legacy `Stream` class with `.prototype`, EventEmitter-shaped
instance methods, and `Readable`/`Writable`/`Duplex`/`Transform`/
`PassThrough`/`pipeline`/`finished` as statics. Add
`export const __perry_commonjs = true;` so the CJS require() shim
returns the class. Split the previously-unreachable `"stream/web"`
match arm. Harden `util.inherits` to throw `TypeError` on missing
prototype and set `ctor.super_`.
- crates/perry-api-manifest/src/entries.rs: register
`property("stream", "prototype")` so the #463 unimplemented-API
gate accepts `Stream.prototype` reads.
- test-files/test_util_inherits.ts (+ V8 fixture): exercises
Stream.prototype, Stream.Readable.prototype, util.inherits with
prototype-chain method resolution, and the `super_` static.
Verified: `import express from 'express'; console.log(typeof express)`
now prints `function` (was `TypeError: Object prototype may only be an
Object or null: undefined`).
This was referenced May 18, 2026
proggeramlug
added a commit
that referenced
this pull request
May 18, 2026
PRs #966, #967, #982, #984 added entries to perry-api-manifest::API_MANIFEST (stream EventEmitter instance methods, stream.prototype, lodash inRange/max/maxBy/mean/meanBy/min/minBy/random/sum/sumBy/tail) without rerunning ./scripts/regen_api_docs.sh. Drift has been blocking the api-docs-drift gate on every subsequent PR; unblocking the next batch. Coverage moves from 870 → 898 entries across 71 modules. Mechanical regen, no manifest edits.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
util.inherits(SendStream, Stream)insidenode_modules/send/index.js:173—Stream.prototypewasundefinedbecause the V8-fallbacknode:streamshim returned a plain{ Readable, Writable, ... }namespace, not the legacyStreamconstructor Node ships.node:streamshim around a realStreamclass with its own.prototypeand EventEmitter-shaped instance methods. AttachReadable/Writable/Duplex/Transform/PassThrough/pipeline/finishedas static properties, thenexport default Stream+export const __perry_commonjs = truesorequire('stream')returns the class itself (matching Node).util.inherits(ctor, superCtor)in thenode:utilshim: input validation,TypeErrorwhensuperCtor.prototypeis undefined (matches Node's message), andObject.defineProperty(ctor, 'super_', ...)for the legacy chaining pattern.property("stream", "prototype")to the API manifest so the Compile-time error for unimplemented Node / Web APIs #463 unimplemented-API gate acceptsStream.prototypereads.Verification
import express from 'express'— previously crashed withAfter this PR:
typeof express === 'function'.test-files/test_util_inherits.ts(V8-routed via.jsfixture, mirrors the express/send pattern):Test plan
cargo build --release -p perry-runtime -p perry-stdlib -p perry-jsruntime -p perrycargo fmt --alltest-files/test_util_inherits.ts— all 8 assertions passimport express from 'express') compiles + runs + printsfunction