diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index bb01e800becdf3..877db6fbe1cb34 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -13,6 +13,18 @@ function isRequest(stream) { return stream.setHeader && typeof stream.abort === 'function'; } +function isReadable(stream) { + return typeof stream.readable === 'boolean' || + typeof stream.readableEnded === 'boolean' || + !!stream._readableState; +} + +function isWritable(stream) { + return typeof stream.writable === 'boolean' || + typeof stream.writableEnded === 'boolean' || + !!stream._writableState; +} + function eos(stream, opts, callback) { if (arguments.length === 2) { callback = opts; @@ -28,8 +40,10 @@ function eos(stream, opts, callback) { callback = once(callback); - let readable = opts.readable || (opts.readable !== false && stream.readable); - let writable = opts.writable || (opts.writable !== false && stream.writable); + let readable = opts.readable || + (opts.readable !== false && isReadable(stream)); + let writable = opts.writable || + (opts.writable !== false && isWritable(stream)); const onlegacyfinish = () => { if (!stream.writable) onfinish(); diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index d6361ea303635d..89fbd6e3bb21ba 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -184,3 +184,52 @@ const { promisify } = require('util'); finished(streamLike, common.mustCall); streamLike.emit('close'); } + + +{ + // Test is readable check through readable + const streamLike = new EE(); + streamLike.readable = false; + finished(streamLike, common.mustCall()); + streamLike.emit('end'); +} + +{ + // Test is readable check through readableEnded + const streamLike = new EE(); + streamLike.readableEnded = true; + finished(streamLike, common.mustCall()); + streamLike.emit('end'); +} + +{ + // Test is readable check through _readableState + const streamLike = new EE(); + streamLike._readableState = {}; + finished(streamLike, common.mustCall()); + streamLike.emit('end'); +} + +{ + // Test is writable check through writable + const streamLike = new EE(); + streamLike.writable = false; + finished(streamLike, common.mustCall()); + streamLike.emit('finish'); +} + +{ + // Test is writable check through writableEnded + const streamLike = new EE(); + streamLike.writableEnded = true; + finished(streamLike, common.mustCall()); + streamLike.emit('finish'); +} + +{ + // Test is writable check through _writableState + const streamLike = new EE(); + streamLike._writableState = {}; + finished(streamLike, common.mustCall()); + streamLike.emit('finish'); +}