diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index 3fcd373cb1c708..4b7613fd13d081 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -1122,7 +1122,7 @@ async function* createAsyncIterator(stream, options) { stream.on('readable', next); let error; - eos(stream, { writable: false }, (err) => { + const cleanup = eos(stream, { writable: false }, (err) => { error = err ? aggregateTwoErrors(error, err) : null; callback(); callback = nop; @@ -1150,6 +1150,9 @@ async function* createAsyncIterator(stream, options) { (error === undefined || stream._readableState.autoDestroy) ) { destroyImpl.destroyer(stream, null); + } else { + stream.off('readable', next); + cleanup(); } } } diff --git a/test/parallel/test-stream-readable-async-iterators.js b/test/parallel/test-stream-readable-async-iterators.js index 87184662139ae5..e8b69612014ca5 100644 --- a/test/parallel/test-stream-readable-async-iterators.js +++ b/test/parallel/test-stream-readable-async-iterators.js @@ -789,6 +789,20 @@ async function tests() { } ); } + + // Check for dangling listeners + (async function() { + const readable = createReadable(); + const opts = { destroyOnReturn: false }; + while (readable.readable) { + // eslint-disable-next-line no-unused-vars + for await (const chunk of readable.iterator(opts)) { + break; + } + } + + assert.deepStrictEqual(readable.eventNames(), []); + })().then(common.mustCall()); } {