Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Nagy <ronagy@icloud.com>2019-07-23 10:40:13 +0300
committerMichaƫl Zasso <targos@protonmail.com>2019-08-20 10:10:17 +0300
commita9f8b62b47588c78651bd0cf34fd1a9078b8d635 (patch)
tree8ecd9229f33f5e60e9fe272751fd14b0058c2c1d
parentf42eb01d1d5158decaaa179a83dd97f021912cf2 (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.md9
-rw-r--r--lib/_stream_readable.js10
-rw-r--r--lib/internal/streams/async_iterator.js2
-rw-r--r--lib/internal/streams/end-of-stream.js3
-rw-r--r--test/parallel/test-stream-finished.js9
-rw-r--r--test/parallel/test-stream-readable-ended.js33
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);
+ }));
+}