From 20f74ecfc4871681e27462e59149bcf82c7c2999 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Sun, 27 Oct 2019 01:09:03 +0200 Subject: [PATCH] stream: extract Readable.from in its own file See: https://github.com/nodejs/readable-stream/pull/420 PR-URL: https://github.com/nodejs/node/pull/30140 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: Gus Caplan Reviewed-By: Beth Griggs --- lib/_stream_readable.js | 39 ++++-------------------------- lib/internal/streams/from.js | 46 ++++++++++++++++++++++++++++++++++++ node.gyp | 1 + 3 files changed, 51 insertions(+), 35 deletions(-) create mode 100644 lib/internal/streams/from.js diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index d3198c7545f1d8..73b4c06c07d42e 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -47,6 +47,7 @@ const { // Lazy loaded to improve the startup performance. let StringDecoder; let createReadableStreamAsyncIterator; +let from; Object.setPrototypeOf(Readable.prototype, Stream.prototype); Object.setPrototypeOf(Readable, Stream); @@ -1194,40 +1195,8 @@ function endReadableNT(state, stream) { } Readable.from = function(iterable, opts) { - let iterator; - if (iterable && iterable[Symbol.asyncIterator]) - iterator = iterable[Symbol.asyncIterator](); - else if (iterable && iterable[Symbol.iterator]) - iterator = iterable[Symbol.iterator](); - else - throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable); - - const readable = new Readable({ - objectMode: true, - ...opts - }); - // Reading boolean to protect against _read - // being called before last iteration completion. - let reading = false; - readable._read = function() { - if (!reading) { - reading = true; - next(); - } - }; - async function next() { - try { - const { value, done } = await iterator.next(); - if (done) { - readable.push(null); - } else if (readable.push(await value)) { - next(); - } else { - reading = false; - } - } catch (err) { - readable.destroy(err); - } + if (from === undefined) { + from = require('internal/streams/from'); } - return readable; + return from(Readable, iterable, opts); }; diff --git a/lib/internal/streams/from.js b/lib/internal/streams/from.js new file mode 100644 index 00000000000000..e809f2658d5a9a --- /dev/null +++ b/lib/internal/streams/from.js @@ -0,0 +1,46 @@ +'use strict'; + +const { + ERR_INVALID_ARG_TYPE +} = require('internal/errors').codes; + +function from(Readable, iterable, opts) { + let iterator; + if (iterable && iterable[Symbol.asyncIterator]) + iterator = iterable[Symbol.asyncIterator](); + else if (iterable && iterable[Symbol.iterator]) + iterator = iterable[Symbol.iterator](); + else + throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable); + + const readable = new Readable({ + objectMode: true, + ...opts + }); + // Reading boolean to protect against _read + // being called before last iteration completion. + let reading = false; + readable._read = function() { + if (!reading) { + reading = true; + next(); + } + }; + async function next() { + try { + const { value, done } = await iterator.next(); + if (done) { + readable.push(null); + } else if (readable.push(await value)) { + next(); + } else { + reading = false; + } + } catch (err) { + readable.destroy(err); + } + } + return readable; +} + +module.exports = from; diff --git a/node.gyp b/node.gyp index aa2b361f9548ac..8f4dc518e1600a 100644 --- a/node.gyp +++ b/node.gyp @@ -205,6 +205,7 @@ 'lib/internal/streams/async_iterator.js', 'lib/internal/streams/buffer_list.js', 'lib/internal/streams/duplexpair.js', + 'lib/internal/streams/from.js', 'lib/internal/streams/legacy.js', 'lib/internal/streams/destroy.js', 'lib/internal/streams/state.js',