Repository navigation
feat(streams): BYOB readers + real ByteLengthQueuingStrategy accounting - #4966
Merged
Merged
Conversation
…ng (#4915) Implements the Web Streams residuals left after #237/#1545: - ReadableStreamBYOBReader: getReader({ mode: "byob" }) and new ReadableStreamBYOBReader(stream) mint readers whose read(view) fills the caller-supplied TypedArray/DataView/Buffer (draining queued byte chunks across chunk boundaries, remainder requeued); done resolves with an empty view per spec. - ReadableByteStreamController.byobRequest: { view, respond(bytesWritten), respondWithNewView(view) } while a read(view) is parked, null otherwise; pull sources write straight into the caller's buffer. - Real QueuingStrategy accounting: per-chunk size() results (or byteLength on byte streams) are summed into desiredSize for ReadableStream, WritableStream, and TransformStream; the WritableStream/TransformStream constructors now accept strategy objects (number-or-object parsing in streams/strategy.rs). - Byte streams default to highWaterMark 0 per spec (no eager pull at construction; ShouldCallPull fires on parked read requests). - Spec-shaped errors: TypeError for BYOB mode on non-byte streams / invalid views / released readers, RangeError for out-of-range bytesWritten; removed the dead js_streams_throw_*_not_implemented stubs (perry-ext-streams + stdlib) and the three #4915 manifest stub notes; regenerated API docs. Verified byte-for-byte against node --experimental-strip-types (test-files/test_parity_streams_byob.ts) and guarded by crates/perry/tests/issue_4915_streams_byob.rs. Streams regression sweep (pipe/user-source/blob/readable/subclass/consumers/stream_web) is byte-identical to origin/main. Fixes #4915
proggeramlug
force-pushed
the
feat/streams-byob-4915
branch
from
June 11, 2026 05:59
5d9a47e to
2c8b2df
Compare
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.
Fixes #4915 (stub-elimination epic #4919).
What
Implements the Web Streams residuals left after #237/#1545 — all three acceptance items:
1.
ReadableStreamBYOBReader—stream.getReader({ mode: "byob" })andnew ReadableStreamBYOBReader(stream)mint readers whoseread(view)fills the caller-supplied TypedArray/DataView/Buffer in place, draining queued byte chunks across chunk boundaries (remainder requeued at the head). Reads at EOF resolve{ value: <empty view>, done: true }. The byte-stream controller exposesbyobRequest—{ view, respond(bytesWritten), respondWithNewView(view) }— non-null while aread(view)is parked, so pull sources write straight into the caller's buffer. Newcrates/perry-stdlib/src/streams/byob.rscarries the implementation (with its own GC root scanning for parked promises/views).2.
ByteLengthQueuingStrategyas a real strategy — per-chunkstrategy.size(chunk)results (computed once at enqueue per spec;byteLengthon byte streams, 1 otherwise) are summed intodesiredSizefor ReadableStream, WritableStream, and TransformStream. The WritableStream/TransformStream constructors now accept whole strategy objects (streams/strategy.rs::parse_strategy_valuehandles number-or-object-or-undefined); TransformStream takes bothwritableStrategyandreadableStrategy. Byte streams default tohighWaterMark: 0per spec — no eager pull at construction; ShouldCallPull fires once a read request is parked.3. Spec-shaped errors — TypeError for BYOB mode on non-byte streams, invalid/zero-length views, released readers, and respond-with-no-request; RangeError (
ERR_OUT_OF_RANGE) for out-of-rangebytesWritten. The deadjs_streams_throw_byob_not_implemented/js_streams_throw_byte_length_not_implementedstubs (cited in the issue atperry-ext-streams/src/lib.rsandstdlib/streams/transform.rs) are removed — nothing routed to them. The three#4915manifest stub notes are dropped and API docs regenerated.streams.rsstayed under the 2000-line CI cap by extracting the #1545 queuing-strategy block intostreams/strategy.rs.Verification
test-files/test_parity_streams_byob.tsis byte-for-byte identical tonode --experimental-strip-types(BYOB multi-chunk reads, mode TypeError,byobRequest.respond, desiredSize accounting on all three constructors, strategy object shape).crates/perry/tests/issue_4915_streams_byob.rs(green).test_issue_237_streams_{pipe,user_source,blob},test_issue_320_readable_streamMATCH Node;test_parity_stream_web,test_issue_562_stream_subclass,test_parity_stream_consumers,test_parity_streamare byte-identical to a fresh origin/main baseline build (their failures are pre-existing Roadmap: Node.js + TypeScript compatibility & stability #793 module-inventory gaps, including the from-iterable dynamic-read loop — verified unchanged).perry-stdliblib tests (96),stub_inventory, fmt, and the file-size gate all pass.No version bump / changelog — maintainer folds metadata at merge per repo convention.