diff options
author | Robert Nagy <ronagy@icloud.com> | 2019-07-23 10:40:13 +0300 |
---|---|---|
committer | Michaƫl Zasso <targos@protonmail.com> | 2019-08-20 10:10:17 +0300 |
commit | a9f8b62b47588c78651bd0cf34fd1a9078b8d635 (patch) | |
tree | 8ecd9229f33f5e60e9fe272751fd14b0058c2c1d | |
parent | f42eb01d1d5158decaaa179a83dd97f021912cf2 (diff) |
stream: add readableEnded
Adds a readableEnded property and improved finished compat with possible
stream-like objects.
PR-URL: https://github.com/nodejs/node/pull/28814
Refs: https://github.com/nodejs/node/issues/28813
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
-rw-r--r-- | doc/api/stream.md | 9 | ||||
-rw-r--r-- | lib/_stream_readable.js | 10 | ||||
-rw-r--r-- | lib/internal/streams/async_iterator.js | 2 | ||||
-rw-r--r-- | lib/internal/streams/end-of-stream.js | 3 | ||||
-rw-r--r-- | test/parallel/test-stream-finished.js | 9 | ||||
-rw-r--r-- | test/parallel/test-stream-readable-ended.js | 33 |
6 files changed, 64 insertions, 2 deletions
diff --git a/doc/api/stream.md b/doc/api/stream.md index 92a3e82bd18..dd379f4d5ad 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -1126,6 +1126,15 @@ added: v12.7.0 Getter for the property `encoding` of a given `Readable` stream. The `encoding` property can be set using the [`readable.setEncoding()`][] method. +##### readable.readableEnded +<!-- YAML +added: REPLACEME +--> + +* {boolean} + +Becomes `true` when [`'end'`][] event is emitted. + ##### readable.readableHighWaterMark <!-- YAML added: v9.3.0 diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 47c177346b7..ad3302e5422 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -196,6 +196,16 @@ Object.defineProperty(Readable.prototype, 'destroyed', { } }); +Object.defineProperty(Readable.prototype, 'readableEnded', { + // Making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get() { + return this._readableState ? this._readableState.endEmitted : false; + } +}); + Readable.prototype.destroy = destroyImpl.destroy; Readable.prototype._undestroy = destroyImpl.undestroy; Readable.prototype._destroy = function(err, cb) { diff --git a/lib/internal/streams/async_iterator.js b/lib/internal/streams/async_iterator.js index 89a1dae7fdf..0161ca98ef0 100644 --- a/lib/internal/streams/async_iterator.js +++ b/lib/internal/streams/async_iterator.js @@ -132,7 +132,7 @@ const createReadableStreamAsyncIterator = (stream) => { [kLastReject]: { value: null, writable: true }, [kError]: { value: null, writable: true }, [kEnded]: { - value: stream._readableState.endEmitted, + value: stream.readableEnded || stream._readableState.endEmitted, writable: true }, // The function passed to new Promise is cached so we avoid allocating a new diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index 1753996a4f8..850e5d3796c 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -42,7 +42,8 @@ function eos(stream, opts, callback) { if (!readable) callback.call(stream); }; - var readableEnded = stream._readableState && stream._readableState.endEmitted; + var readableEnded = stream.readableEnded || + (stream._readableState && stream._readableState.endEmitted); const onend = () => { readable = false; readableEnded = true; diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index 329b4ed42b0..d6361ea3036 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -3,6 +3,7 @@ const common = require('../common'); const { Writable, Readable, Transform, finished } = require('stream'); const assert = require('assert'); +const EE = require('events'); const fs = require('fs'); const { promisify } = require('util'); @@ -175,3 +176,11 @@ const { promisify } = require('util'); rs.push(null); rs.resume(); } + +{ + const streamLike = new EE(); + streamLike.readableEnded = true; + streamLike.readable = true; + finished(streamLike, common.mustCall); + streamLike.emit('close'); +} diff --git a/test/parallel/test-stream-readable-ended.js b/test/parallel/test-stream-readable-ended.js new file mode 100644 index 00000000000..a224c68f041 --- /dev/null +++ b/test/parallel/test-stream-readable-ended.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common'); +const { Readable } = require('stream'); +const assert = require('assert'); + +// basic +{ + // Find it on Readable.prototype + assert(Readable.prototype.hasOwnProperty('readableEnded')); +} + +// event +{ + const readable = new Readable(); + + readable._read = () => { + // The state ended should start in false. + assert.strictEqual(readable.readableEnded, false); + readable.push('asd'); + assert.strictEqual(readable.readableEnded, false); + readable.push(null); + assert.strictEqual(readable.readableEnded, false); + }; + + readable.on('end', common.mustCall(() => { + assert.strictEqual(readable.readableEnded, true); + })); + + readable.on('data', common.mustCall(() => { + assert.strictEqual(readable.readableEnded, false); + })); +} |