From 0778f79cb37526c3f4f8bff525fc4d4ca9b86e78 Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Thu, 25 Jan 2018 15:40:10 +0100 Subject: [PATCH] stream: do not emit readable if the stream ended Fixes a regression introduced by the once-per-microtick 'readable' event emission. See: https://github.com/nodejs/node/pull/17979 PR-URL: https://github.com/nodejs/node/pull/18372 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/_stream_readable.js | 4 +- ...st-stream-readable-no-unneeded-readable.js | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-stream-readable-no-unneeded-readable.js diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 9cf786a15be847..364f2ba7444bb4 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -520,7 +520,9 @@ function emitReadable(stream) { function emitReadable_(stream) { var state = stream._readableState; debug('emit readable'); - stream.emit('readable'); + if (!state.destroyed && (state.length || state.ended)) { + stream.emit('readable'); + } state.needReadable = !state.flowing && !state.ended; flow(stream); } diff --git a/test/parallel/test-stream-readable-no-unneeded-readable.js b/test/parallel/test-stream-readable-no-unneeded-readable.js new file mode 100644 index 00000000000000..bd3e06e5f7d55c --- /dev/null +++ b/test/parallel/test-stream-readable-no-unneeded-readable.js @@ -0,0 +1,39 @@ +'use strict'; +const common = require('../common'); +const { Readable, PassThrough } = require('stream'); + +const source = new Readable({ + read: () => {} +}); + +source.push('foo'); +source.push('bar'); +source.push(null); + +const pt = source.pipe(new PassThrough()); + +const wrapper = new Readable({ + read: () => { + let data = pt.read(); + + if (data) { + wrapper.push(data); + return; + } + + pt.once('readable', function() { + data = pt.read(); + if (data) { + wrapper.push(data); + } + // else the end event should fire + }); + } +}); + +pt.once('end', function() { + wrapper.push(null); +}); + +wrapper.resume(); +wrapper.once('end', common.mustCall());