diff --git a/lib/internal/webstreams/adapters.js b/lib/internal/webstreams/adapters.js index 6c2be59a24a72a..4db8e0ab28b83e 100644 --- a/lib/internal/webstreams/adapters.js +++ b/lib/internal/webstreams/adapters.js @@ -67,6 +67,7 @@ const { createDeferredPromise, kEmptyObject, normalizeEncoding, + once, } = require('internal/util'); const { @@ -471,7 +472,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj streamReadable.pause(); - const cleanup = finished(streamReadable, (error) => { + const onFinished = once((error) => { error = handleKnownInternalErrors(error); cleanup(); @@ -482,6 +483,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj return controller.error(error); controller.close(); }); + const cleanup = finished(streamReadable, onFinished); streamReadable.on('data', onData); @@ -491,7 +493,9 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj pull() { streamReadable.resume(); }, cancel(reason) { - destroy(streamReadable, reason); + const error = reason || new ERR_STREAM_PREMATURE_CLOSE(); + onFinished(error); + destroy(streamReadable, error); }, }, strategy); } diff --git a/test/parallel/test-stream-readable-from-web-termination.js b/test/parallel/test-stream-readable-from-web-termination.js new file mode 100644 index 00000000000000..68ed7d69694089 --- /dev/null +++ b/test/parallel/test-stream-readable-from-web-termination.js @@ -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(); + }); +} diff --git a/test/parallel/test-stream-readable-to-web-termination.js b/test/parallel/test-stream-readable-to-web-termination.js new file mode 100644 index 00000000000000..13fce9bc715e1e --- /dev/null +++ b/test/parallel/test-stream-readable-to-web-termination.js @@ -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(); +}