Skip to content

stream: fix pipeTo to defer writes per WHATWG spec#61800

Open
mcollina wants to merge 1 commit intonodejs:mainfrom
mcollina:fix-pipeto-spec-compliance
Open

stream: fix pipeTo to defer writes per WHATWG spec#61800
mcollina wants to merge 1 commit intonodejs:mainfrom
mcollina:fix-pipeto-spec-compliance

Conversation

@mcollina
Copy link
Member

Summary

  • Fix PipeToReadableStreamReadRequest[kChunk] to defer writes via queueMicrotask() per the WHATWG Streams spec
  • The spec requires that pipeTo's chunk steps must not synchronously call the write algorithm during enqueue()
  • Remove expected WPT test failure for "enqueue() must not synchronously call write algorithm"

Details

Previously, PipeToReadableStreamReadRequest[kChunk] would synchronously call writableStreamDefaultWriterWrite(), which violated the WHATWG Streams spec (ReadableStreamPipeTo step 15's "chunk steps").

This caused the WPT test piping/general-addition.any.js"enqueue() must not synchronously call write algorithm" to fail, which was tracked as an expected failure (see whatwg/streams#1243).

Wrapping the write in queueMicrotask() defers it to the next microtask, matching the spec's required timing semantics.

Refs: whatwg/streams#1243

Test plan

  • WPT streams tests pass (test/wpt/test-streams.js)
  • Previously expected failure now passes
  • All test/parallel/test-webstreams-*.js tests pass

The WHATWG Streams spec requires that pipeTo's chunk handling must
queue a microtask before calling the write algorithm. This ensures
that enqueue() does not synchronously trigger writes.

Previously, PipeToReadableStreamReadRequest[kChunk] would synchronously
call writableStreamDefaultWriterWrite(), which violated the spec and
caused the WPT test "enqueue() must not synchronously call write
algorithm" to fail.

Fix by wrapping the write operation in queueMicrotask(), which defers
it to the next microtask as required by the spec.

Refs: whatwg/streams#1243
@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/web-standards

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. web streams labels Feb 13, 2026
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.74%. Comparing base (ae2ffce) to head (f599463).
⚠️ Report is 69 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61800      +/-   ##
==========================================
- Coverage   89.75%   89.74%   -0.01%     
==========================================
  Files         674      675       +1     
  Lines      204416   204679     +263     
  Branches    39285    39337      +52     
==========================================
+ Hits       183472   183697     +225     
- Misses      13227    13282      +55     
+ Partials     7717     7700      -17     
Files with missing lines Coverage Δ
lib/internal/webstreams/readablestream.js 98.45% <100.00%> (+<0.01%) ⬆️

... and 66 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always thought this one was a bit silly but ok.

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Feb 13, 2026
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Feb 13, 2026
@nodejs-github-bot
Copy link
Collaborator

@MattiasBuelens
Copy link
Contributor

Previously, PipeToReadableStreamReadRequest[kChunk] would synchronously call writableStreamDefaultWriterWrite(), which violated the WHATWG Streams spec (ReadableStreamPipeTo step 15's "chunk steps").

Is it just me, or does this not even appear in the spec text? Step 15 doesn't even mention "chunk steps". 🤔

I agree that the specification for ReadableStreamPipeTo leaves a lot of choices up to the implementor, even though the WPT tests require a lot of specific timings...

Comment on lines -5 to -12
"piping/general-addition.any.js": {
"fail": {
"note": "Blocked on https://github.com/whatwg/streams/issues/1243",
"expected": [
"enqueue() must not synchronously call write algorithm"
]
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even the reference implementation skips this test. 😅

Is this extra microtask now a "de facto" standard? Looking at wpt.fyi, all major browsers are already passing this test, even though the spec text doesn't require it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. web streams

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants