mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
lib: fix unhandled errors in webstream adapters
WebStream's Readable controller does not tolerate `.close()` being called after an `error`. However, when wrapping a Node's Readable stream it is possible that the sequence of events leads to `finished()`'s callback being invoked after such `error`. In order to handle this, in this change we call the `finished()` handler earlier when controller is canceled, and always handle this as an error case. Fix: https://github.com/nodejs/node/issues/54205 PR-URL: https://github.com/nodejs/node/pull/54206 Fixes: https://github.com/nodejs/node/issues/54205 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Mattias Buelens <mattias@buelens.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
parent
e2c62203cc
commit
78150f3e9c
@ -459,6 +459,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj
|
||||
const strategy = evaluateStrategyOrFallback(options?.strategy);
|
||||
|
||||
let controller;
|
||||
let wasCanceled = false;
|
||||
|
||||
function onData(chunk) {
|
||||
// Copy the Buffer to detach it from the pool.
|
||||
@ -480,6 +481,10 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj
|
||||
streamReadable.on('error', () => {});
|
||||
if (error)
|
||||
return controller.error(error);
|
||||
// Was already canceled
|
||||
if (wasCanceled) {
|
||||
return;
|
||||
}
|
||||
controller.close();
|
||||
});
|
||||
|
||||
@ -491,6 +496,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj
|
||||
pull() { streamReadable.resume(); },
|
||||
|
||||
cancel(reason) {
|
||||
wasCanceled = true;
|
||||
destroy(streamReadable, reason);
|
||||
},
|
||||
}, strategy);
|
||||
|
15
test/parallel/test-stream-readable-from-web-termination.js
Normal file
15
test/parallel/test-stream-readable-from-web-termination.js
Normal file
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const { Readable } = require('stream');
|
||||
|
||||
{
|
||||
const r = Readable.from(['data']);
|
||||
|
||||
const wrapper = Readable.fromWeb(Readable.toWeb(r));
|
||||
|
||||
wrapper.on('data', () => {
|
||||
// Destroying wrapper while emitting data should not cause uncaught
|
||||
// exceptions
|
||||
wrapper.destroy();
|
||||
});
|
||||
}
|
12
test/parallel/test-stream-readable-to-web-termination.js
Normal file
12
test/parallel/test-stream-readable-to-web-termination.js
Normal file
@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const { Readable } = require('stream');
|
||||
|
||||
{
|
||||
const r = Readable.from([]);
|
||||
// Cancelling reader while closing should not cause uncaught exceptions
|
||||
r.on('close', () => reader.cancel());
|
||||
|
||||
const reader = Readable.toWeb(r).getReader();
|
||||
reader.read();
|
||||
}
|
Loading…
Reference in New Issue
Block a user