Skip to content

Commit

Permalink
stream: do not chunk strings and Buffer in Readable.from
Browse files Browse the repository at this point in the history
PR-URL: #30912
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
mcollina authored and MylesBorins committed Dec 17, 2019
1 parent df5ae1a commit 0c18c49
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
4 changes: 4 additions & 0 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,10 @@ readable.on('data', (chunk) => {
});
```

Calling `Readable.from(string)` or `Readable.from(buffer)` will not have
the strings or buffers be iterated to match the other streams semantics
for performance reasons.

## API for Stream Implementers

<!--type=misc-->
Expand Down
12 changes: 12 additions & 0 deletions lib/internal/streams/from.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ const {
Symbol,
SymbolIterator
} = primordials;
const { Buffer } = require('buffer');

const {
ERR_INVALID_ARG_TYPE
} = require('internal/errors').codes;

function from(Readable, iterable, opts) {
let iterator;
if (typeof iterable === 'string' || iterable instanceof Buffer) {
return new Readable({
objectMode: true,
...opts,
read() {
this.push(iterable);
this.push(null);
}
});
}

if (iterable && iterable[Symbol.asyncIterator])
iterator = iterable[Symbol.asyncIterator]();
else if (iterable && iterable[SymbolIterator])
Expand Down
13 changes: 12 additions & 1 deletion test/parallel/test-readable-from.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,23 @@ async function toReadablePromises() {
async function toReadableString() {
const stream = Readable.from('abc');

const expected = ['a', 'b', 'c'];
const expected = ['abc'];

for await (const chunk of stream) {
strictEqual(chunk, expected.shift());
}
}

async function toReadableBuffer() {
const stream = Readable.from(Buffer.from('abc'));

const expected = ['abc'];

for await (const chunk of stream) {
strictEqual(chunk.toString(), expected.shift());
}
}

async function toReadableOnData() {
async function* generate() {
yield 'a';
Expand Down Expand Up @@ -154,6 +164,7 @@ Promise.all([
toReadableSyncIterator(),
toReadablePromises(),
toReadableString(),
toReadableBuffer(),
toReadableOnData(),
toReadableOnDataNonObject(),
destroysTheStreamWhenThrowing(),
Expand Down

0 comments on commit 0c18c49

Please sign in to comment.