Skip to content

stream: run a replaced write() in the flowing pipe - #66596

Open
nigrosimone wants to merge 1 commit into
nodejs:mainfrom
nigrosimone:stream-pipe-replaced-write
Open

nigrosimone wants to merge 1 commit into
nodejs:mainfrom
nigrosimone:stream-pipe-replaced-write

Conversation

@nigrosimone

Copy link
Copy Markdown
Contributor

pipe() calls dest.write(), but since #66182 a flowing pipe whose source pushes from _read() hands each chunk to dest._write() directly. A write() replaced on the destination, or overridden in a subclass, no longer runs.

Found on 26.11.1 with a framework whose response is a stream.Writable: compression middleware replaces res.write(), and a file piped to the response came out as a gzip body with uncompressed chunks in it (Z_DATA_ERROR on the client). 26.10.0 is fine.

Fix: take the fast path only when write() is Writable.prototype.write.

Test: test/parallel/test-stream-pipe-replaced-write.js, one write() replaced on the instance and one in a subclass. It fails on 26.11.1 (1 call to write() out of 64) and passes with the fix.

cc @anonrig

Disclosure: I used Opus 5.5 (Max) as coding assistant

pipe() calls dest.write(). The fast path of a flowing pipe hands the
chunks of a source that pushes from _read() to dest._write() directly,
so a write() replaced on the instance or overridden in a subclass no
longer runs. A response that is a Writable, wrapped by compression
middleware, sent a gzip body with uncompressed chunks in it.

Take the fast path only when write() is Writable.prototype.write.

Refs: nodejs#66182
Signed-off-by: Nigro Simone <nigro.simone@gmail.com>
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/streams

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. stream Issues and PRs related to Node.js streams. labels Oct 8, 2026
@mcollina

mcollina commented Oct 8, 2026

Copy link
Copy Markdown
Member

@nigrosimone this seems good, why it's draft?

@nigrosimone

nigrosimone commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

@mcollina my local build is still running, I want to see the test pass there first. Ready in about an hour, or I can mark it ready now and let the CI run, if you prefer.

@nigrosimone
nigrosimone marked this pull request as ready for review October 8, 2026 08:53
@codecov

codecov Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.44%. Comparing base (6d5e309) to head (d603f99).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #66596   +/-   ##
=======================================
  Coverage   90.44%   90.44%           
=======================================
  Files         791      791           
  Lines      276562   276565    +3     
  Branches    53126    53116   -10     
=======================================
+ Hits       250130   250138    +8     
+ Misses      16846    16834   -12     
- Partials     9586     9593    +7     
Files with missing lines Coverage Δ
lib/internal/streams/writable.js 96.43% <100.00%> (+<0.01%) ⬆️

... and 30 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.

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. stream Issues and PRs related to Node.js streams.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants