Skip to content

Comments

webstreams: accept ArrayBuffer in WritableStream write sink#61913

Open
suuuuuuminnnnnn wants to merge 6 commits intonodejs:mainfrom
suuuuuuminnnnnn:fix/webstreams-arraybuffer-write
Open

webstreams: accept ArrayBuffer in WritableStream write sink#61913
suuuuuuminnnnnn wants to merge 6 commits intonodejs:mainfrom
suuuuuuminnnnnn:fix/webstreams-arraybuffer-write

Conversation

@suuuuuuminnnnnn
Copy link

@suuuuuuminnnnnn suuuuuuminnnnnn commented Feb 21, 2026

Per the WHATWG Compression Streams spec, CompressionStream and
DecompressionStream must accept BufferSource
(ArrayBuffer | ArrayBufferView) as valid chunk types.

Currently, writing a plain ArrayBuffer to the writable side throws
ERR_INVALID_ARG_TYPE, because the adapter in
newWritableStreamFromStreamWritable passes chunks directly to
stream.write(), which only accepts ArrayBufferView types.

This change normalizes plain ArrayBuffer chunks to a Uint8Array view
before forwarding them to the underlying Node.js stream.

Changes included:

  • normalize ArrayBuffer to Uint8Array in lib/internal/webstreams/adapters.js
  • add a regression test for ArrayBuffer input
  • unskip the relevant WPT compression BufferSource test (if passing)

Fixes: #43433

@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 21, 2026
@suuuuuuminnnnnn suuuuuuminnnnnn force-pushed the fix/webstreams-arraybuffer-write branch from 30ebba1 to 91009bf Compare February 21, 2026 05:04
Comment on lines 20 to 26
const chunks = [];
let done = false;
while (!done) {
const { value, done: d } = await reader.read();
if (value) chunks.push(value);
done = d;
}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Similar to Mattias's comment, this iteration doesn't need to be done manually:

Suggested change
const chunks = [];
let done = false;
while (!done) {
const { value, done: d } = await reader.read();
if (value) chunks.push(value);
done = d;
}
const chunks = await Array.fromAsync(ds.readable);

Copy link
Contributor

Choose a reason for hiding this comment

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

@suuuuuuminnnnnn Please take a look 🙂

Copy link
Author

Choose a reason for hiding this comment

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

Good catch, thanks both — I'll apply this suggestion too.

@codecov
Copy link

codecov bot commented Feb 21, 2026

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61913      +/-   ##
==========================================
- Coverage   89.75%   89.75%   -0.01%     
==========================================
  Files         674      674              
  Lines      204416   204893     +477     
  Branches    39285    39377      +92     
==========================================
+ Hits       183472   183892     +420     
- Misses      13227    13283      +56     
- Partials     7717     7718       +1     
Files with missing lines Coverage Δ
lib/internal/webstreams/adapters.js 85.75% <100.00%> (+0.17%) ⬆️

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

@suuuuuuminnnnnn
Copy link
Author

Thanks @MattiasBuelens and @Renegade334 — applied both suggestions.

  • added the object mode guard before normalizing ArrayBuffer
  • replaced the manual read loop with Array.fromAsync(...)
  • replaced the manual piping/write loop with await cs.readable.pipeTo(ds.writable)

I kept the PR scoped to the ArrayBuffer handling fix + regression coverage.
Appreciate the review.

@MattiasBuelens MattiasBuelens added the request-ci Add this label to start a Jenkins CI on a PR. label Feb 21, 2026
@github-actions github-actions bot added request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Feb 21, 2026
@github-actions
Copy link
Contributor

Failed to start CI
   ⚠  No approving reviews found
   ✘  Refusing to run CI on potentially unsafe PR
https://github.com/nodejs/node/actions/runs/22255119973

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

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

Comment on lines 40 to 46
const out = [];
let done = false;
while (!done) {
const { value, done: d } = await dsReader.read();
if (value) out.push(value);
done = d;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit-pick: you could also use Array.fromAsync here. 😉

Copy link
Author

Choose a reason for hiding this comment

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

Done, applied to both tests. Thanks!

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. request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. web streams

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Writer cannot cope with ArrayBuffer

6 participants