stream: allow shared array buffer sources in writable webstream adapter

Refs: https://github.com/nodejs/node/pull/61913
Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: https://github.com/nodejs/node/pull/62163
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
This commit is contained in:
René authored and GitHub committed 2026-04-13 15:42:29 +00:00
1 parent c7d05fc0d3
commit 9cae81932c
3 files changed
+100 -5

No files matched your search

+4 -4
View File
@@ -56,7 +56,7 @@ const {
} = require('buffer');
const {
isArrayBuffer,
isAnyArrayBuffer,
} = require('internal/util/types');
const {
@@ -231,11 +231,11 @@ function newWritableStreamFromStreamWritable(streamWritable, options = kEmptyObj
start(c) { controller = c; },
write(chunk) {
if (!streamWritable.writableObjectMode && isArrayBuffer(chunk)) {
chunk = new Uint8Array(chunk);
}
try {
options[kValidateChunk]?.(chunk);
if (!streamWritable.writableObjectMode && isAnyArrayBuffer(chunk)) {
chunk = new Uint8Array(chunk);
}
if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) {
backpressurePromise = PromiseWithResolvers();
return SafePromisePrototypeFinally(
+1 -1
View File
@@ -40,7 +40,7 @@ function lazyZlib() {
// Per the Compression Streams spec, chunks must be BufferSource
// (ArrayBuffer or ArrayBufferView not backed by SharedArrayBuffer).
function validateBufferSourceChunk(chunk) {
if (isArrayBufferView(chunk) && isSharedArrayBuffer(chunk.buffer)) {
if (isSharedArrayBuffer(isArrayBufferView(chunk) ? chunk.buffer : chunk)) {
throw new ERR_INVALID_ARG_TYPE(
'chunk',
['ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
@@ -0,0 +1,95 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const { Buffer } = require('buffer');
const { Duplex, Writable } = require('stream');
const { suite, test } = require('node:test');
const ctors = [ArrayBuffer, SharedArrayBuffer];
suite('underlying Writable', () => {
suite('in non-object mode', () => {
for (const ctor of ctors) {
test(`converts ${ctor.name} chunks`, async () => {
const buffer = new ctor(4);
const writable = new Writable({
objectMode: false,
write: common.mustCall((chunk, encoding, callback) => {
assert(Buffer.isBuffer(chunk));
assert.strictEqual(chunk.buffer, buffer);
callback();
}),
});
writable.on('error', common.mustNotCall());
const writer = Writable.toWeb(writable).getWriter();
await writer.write(buffer);
});
}
});
suite('in object mode', () => {
for (const ctor of ctors) {
test(`passes through ${ctor.name} chunks`, async () => {
const buffer = new ctor(4);
const writable = new Writable({
objectMode: true,
write: common.mustCall((chunk, encoding, callback) => {
assert(chunk instanceof ctor);
assert.strictEqual(chunk, buffer);
callback();
}),
});
writable.on('error', common.mustNotCall());
const writer = Writable.toWeb(writable).getWriter();
await writer.write(buffer);
});
}
});
});
suite('underlying Duplex', () => {
suite('in non-object mode', () => {
for (const ctor of ctors) {
test(`converts ${ctor.name} chunks`, async () => {
const buffer = new ctor(4);
const duplex = new Duplex({
writableObjectMode: false,
write: common.mustCall((chunk, encoding, callback) => {
assert(Buffer.isBuffer(chunk));
assert.strictEqual(chunk.buffer, buffer);
callback();
}),
read() {
this.push(null);
},
});
duplex.on('error', common.mustNotCall());
const writer = Duplex.toWeb(duplex).writable.getWriter();
await writer.write(buffer);
});
}
});
suite('in object mode', () => {
for (const ctor of ctors) {
test(`passes through ${ctor.name} chunks`, async () => {
const buffer = new ctor(4);
const duplex = new Duplex({
writableObjectMode: true,
write: common.mustCall((chunk, encoding, callback) => {
assert(chunk instanceof ctor);
assert.strictEqual(chunk, buffer);
callback();
}),
read() {
this.push(null);
},
});
duplex.on('error', common.mustNotCall());
const writer = Duplex.toWeb(duplex).writable.getWriter();
await writer.write(buffer);
});
}
});
});