Skip to content

Commit cb6ff03

Browse files
stream: accept ArrayBuffer in CompressionStream and DecompressionStream
PR-URL: #61913 Fixes: #43433 Reviewed-By: Mattias Buelens <mattias@buelens.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Jason Zhang <xzha4350@gmail.com> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent ddecee7 commit cb6ff03

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

lib/internal/webstreams/adapters.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ const {
5353
Buffer,
5454
} = require('buffer');
5555

56+
const {
57+
isArrayBuffer,
58+
} = require('internal/util/types');
59+
5660
const {
5761
AbortError,
5862
ErrnoException,
@@ -213,6 +217,9 @@ function newWritableStreamFromStreamWritable(streamWritable) {
213217
start(c) { controller = c; },
214218

215219
write(chunk) {
220+
if (!streamWritable.writableObjectMode && isArrayBuffer(chunk)) {
221+
chunk = new Uint8Array(chunk);
222+
}
216223
if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) {
217224
backpressurePromise = PromiseWithResolvers();
218225
return SafePromisePrototypeFinally(
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const test = require('node:test');
5+
const { DecompressionStream, CompressionStream } = require('stream/web');
6+
7+
// Minimal gzip-compressed bytes for "hello"
8+
const compressedGzip = new Uint8Array([
9+
31, 139, 8, 0, 0, 0, 0, 0, 0, 3,
10+
203, 72, 205, 201, 201, 7, 0, 134, 166, 16, 54, 5, 0, 0, 0,
11+
]);
12+
13+
test('DecompressionStream accepts ArrayBuffer chunks', async () => {
14+
const ds = new DecompressionStream('gzip');
15+
const writer = ds.writable.getWriter();
16+
17+
const writePromise = writer.write(compressedGzip.buffer);
18+
writer.close();
19+
20+
const chunks = await Array.fromAsync(ds.readable);
21+
await writePromise;
22+
const out = Buffer.concat(chunks.map((c) => Buffer.from(c)));
23+
assert.strictEqual(out.toString(), 'hello');
24+
});
25+
26+
test('CompressionStream round-trip with ArrayBuffer input', async () => {
27+
const cs = new CompressionStream('gzip');
28+
const ds = new DecompressionStream('gzip');
29+
30+
const csWriter = cs.writable.getWriter();
31+
32+
const input = new TextEncoder().encode('hello').buffer;
33+
34+
await csWriter.write(input);
35+
csWriter.close();
36+
37+
await cs.readable.pipeTo(ds.writable);
38+
39+
const out = await Array.fromAsync(ds.readable);
40+
const result = Buffer.concat(out.map((c) => Buffer.from(c)));
41+
assert.strictEqual(result.toString(), 'hello');
42+
});

test/parallel/test-whatwg-webstreams-adapters-to-writablestream.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,35 @@ class TestWritable extends Writable {
165165
const writer = writableStream.getWriter();
166166
writer.closed.then(common.mustCall());
167167
}
168+
169+
{
170+
const duplex = new PassThrough();
171+
const writableStream = newWritableStreamFromStreamWritable(duplex);
172+
const ec = new TextEncoder();
173+
const arrayBuffer = ec.encode('hello').buffer;
174+
writableStream
175+
.getWriter()
176+
.write(arrayBuffer)
177+
.then(common.mustCall());
178+
179+
duplex.on('data', common.mustCall((chunk) => {
180+
assert(chunk instanceof Buffer);
181+
assert(chunk.equals(Buffer.from('hello')));
182+
}));
183+
}
184+
185+
{
186+
const duplex = new PassThrough({ objectMode: true });
187+
const writableStream = newWritableStreamFromStreamWritable(duplex);
188+
const ec = new TextEncoder();
189+
const arrayBuffer = ec.encode('hello').buffer;
190+
writableStream
191+
.getWriter()
192+
.write(arrayBuffer)
193+
.then(common.mustCall());
194+
195+
duplex.on('data', common.mustCall((chunk) => {
196+
assert(chunk instanceof ArrayBuffer);
197+
assert.strictEqual(chunk, arrayBuffer);
198+
}));
199+
}

test/wpt/status/compression.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
"decompression-bad-chunks.tentative.any.js": {
66
"skip": "Execution \"hangs\", ArrayBuffer and TypedArray is not accepted and throws, instead of rejects during writer.write"
77
},
8-
"decompression-buffersource.tentative.any.js": {
9-
"skip": "ArrayBuffer and TypedArray is not accepted and throws, instead of rejects during writer.write"
10-
},
118
"compression-with-detach.tentative.window.js": {
129
"requires": ["crypto"]
1310
},

0 commit comments

Comments
 (0)