mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 18:25:13 +08:00
Pass rejectGarbageAfterEnd: true to createInflateRaw() and createBrotliDecompress(), matching the behavior already in place for deflate and gzip. The Compression Streams spec treats any data following a valid compressed payload as an error. When the underlying Node.js stream throws synchronously from write() (e.g. zlib rejects an invalid chunk type), destroy the stream so that the readable side is also errored. Without this, the readable side hangs forever waiting for data that will never arrive. Introduce a kValidateChunk callback option in the webstreams adapter layer. Compression streams use this to validate that chunks are BufferSource instances not backed by SharedArrayBuffer, replacing the previous monkey-patching of the underlying handle's write method. Unskip WPT compression bad-chunks tests which now run instead of hang and mark the remaining expected failures. PR-URL: https://github.com/nodejs/node/pull/62107 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Mattias Buelens <mattias@buelens.com> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
80 lines
2.3 KiB
JavaScript
80 lines
2.3 KiB
JavaScript
'use strict';
|
|
// Flags: --no-warnings --expose-internals
|
|
require('../common');
|
|
const assert = require('assert');
|
|
const test = require('node:test');
|
|
const { Duplex, Writable } = require('stream');
|
|
const {
|
|
newWritableStreamFromStreamWritable,
|
|
newReadableWritablePairFromDuplex,
|
|
} = require('internal/webstreams/adapters');
|
|
|
|
// Verify that when the underlying Node.js stream throws synchronously from
|
|
// write(), the writable web stream properly rejects but does not destroy
|
|
// the stream (destroy-on-sync-throw is only used internally by
|
|
// CompressionStream/DecompressionStream).
|
|
|
|
test('WritableStream from Node.js stream handles sync write throw', async () => {
|
|
const error = new TypeError('invalid chunk');
|
|
const writable = new Writable({
|
|
write() {
|
|
throw error;
|
|
},
|
|
});
|
|
|
|
const ws = newWritableStreamFromStreamWritable(writable);
|
|
const writer = ws.getWriter();
|
|
|
|
await assert.rejects(writer.write('bad'), (err) => {
|
|
assert.strictEqual(err, error);
|
|
return true;
|
|
});
|
|
|
|
// Standalone writable should not be destroyed on sync write error
|
|
assert.strictEqual(writable.destroyed, false);
|
|
});
|
|
|
|
test('Duplex-backed pair does NOT destroy on sync write throw', async () => {
|
|
const error = new TypeError('invalid chunk');
|
|
const duplex = new Duplex({
|
|
read() {},
|
|
write() {
|
|
throw error;
|
|
},
|
|
});
|
|
|
|
const { writable, readable } = newReadableWritablePairFromDuplex(duplex);
|
|
const writer = writable.getWriter();
|
|
|
|
await assert.rejects(writer.write('bad'), (err) => {
|
|
assert.strictEqual(err, error);
|
|
return true;
|
|
});
|
|
|
|
// A plain Duplex should NOT be destroyed on sync write error
|
|
assert.strictEqual(duplex.destroyed, false);
|
|
|
|
// The readable side should still be usable
|
|
const reader = readable.getReader();
|
|
reader.cancel();
|
|
});
|
|
|
|
test('WritableStream from Node.js stream - valid writes still work', async () => {
|
|
const chunks = [];
|
|
const writable = new Writable({
|
|
write(chunk, _encoding, cb) {
|
|
chunks.push(chunk);
|
|
cb();
|
|
},
|
|
});
|
|
|
|
const ws = newWritableStreamFromStreamWritable(writable);
|
|
const writer = ws.getWriter();
|
|
|
|
await writer.write(Buffer.from('hello'));
|
|
await writer.write(Buffer.from(' world'));
|
|
await writer.close();
|
|
|
|
assert.strictEqual(Buffer.concat(chunks).toString(), 'hello world');
|
|
});
|