stream: initial approach to include strategy options on Readable.toWeb()
PR-URL: https://github.com/nodejs/node/pull/43515 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
90bc773fb8
commit
99b109f7f3
@ -2807,7 +2807,7 @@ added:
|
|||||||
|
|
||||||
Returns whether the stream is readable.
|
Returns whether the stream is readable.
|
||||||
|
|
||||||
### `stream.Readable.toWeb(streamReadable)`
|
### `stream.Readable.toWeb(streamReadable[, options])`
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v17.0.0
|
added: v17.0.0
|
||||||
@ -2816,6 +2816,10 @@ added: v17.0.0
|
|||||||
> Stability: 1 - Experimental
|
> Stability: 1 - Experimental
|
||||||
|
|
||||||
* `streamReadable` {stream.Readable}
|
* `streamReadable` {stream.Readable}
|
||||||
|
* `options` {Object}
|
||||||
|
* `strategy` {Object}
|
||||||
|
* `highWaterMark` {number}
|
||||||
|
* `size` {Function}
|
||||||
* Returns: {ReadableStream}
|
* Returns: {ReadableStream}
|
||||||
|
|
||||||
### `stream.Writable.fromWeb(writableStream[, options])`
|
### `stream.Writable.fromWeb(writableStream[, options])`
|
||||||
|
@ -1405,8 +1405,10 @@ Readable.fromWeb = function(readableStream, options) {
|
|||||||
options);
|
options);
|
||||||
};
|
};
|
||||||
|
|
||||||
Readable.toWeb = function(streamReadable) {
|
Readable.toWeb = function(streamReadable, options) {
|
||||||
return lazyWebStreams().newReadableStreamFromStreamReadable(streamReadable);
|
return lazyWebStreams().newReadableStreamFromStreamReadable(
|
||||||
|
streamReadable,
|
||||||
|
options);
|
||||||
};
|
};
|
||||||
|
|
||||||
Readable.wrap = function(src, options) {
|
Readable.wrap = function(src, options) {
|
||||||
|
@ -359,10 +359,14 @@ function newStreamWritableFromWritableStream(writableStream, options = kEmptyObj
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {import('./queuingstrategies').QueuingStrategy} QueuingStrategy
|
||||||
* @param {Readable} streamReadable
|
* @param {Readable} streamReadable
|
||||||
|
* @param {{
|
||||||
|
* strategy : QueuingStrategy
|
||||||
|
* }} [options]
|
||||||
* @returns {ReadableStream}
|
* @returns {ReadableStream}
|
||||||
*/
|
*/
|
||||||
function newReadableStreamFromStreamReadable(streamReadable) {
|
function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObject) {
|
||||||
// Not using the internal/streams/utils isReadableNodeStream utility
|
// Not using the internal/streams/utils isReadableNodeStream utility
|
||||||
// here because it will return false if streamReadable is a Duplex
|
// here because it will return false if streamReadable is a Duplex
|
||||||
// whose readable option is false. For a Duplex that is not readable,
|
// whose readable option is false. For a Duplex that is not readable,
|
||||||
@ -382,14 +386,26 @@ function newReadableStreamFromStreamReadable(streamReadable) {
|
|||||||
|
|
||||||
const objectMode = streamReadable.readableObjectMode;
|
const objectMode = streamReadable.readableObjectMode;
|
||||||
const highWaterMark = streamReadable.readableHighWaterMark;
|
const highWaterMark = streamReadable.readableHighWaterMark;
|
||||||
// When not running in objectMode explicitly, we just fall
|
|
||||||
// back to a minimal strategy that just specifies the highWaterMark
|
const evaluateStrategyOrFallback = (strategy) => {
|
||||||
// and no size algorithm. Using a ByteLengthQueuingStrategy here
|
// If there is a strategy available, use it
|
||||||
// is unnecessary.
|
if (strategy)
|
||||||
const strategy =
|
return strategy;
|
||||||
objectMode ?
|
|
||||||
new CountQueuingStrategy({ highWaterMark }) :
|
if (objectMode) {
|
||||||
{ highWaterMark };
|
// When running in objectMode explicitly but no strategy, we just fall
|
||||||
|
// back to CountQueuingStrategy
|
||||||
|
return new CountQueuingStrategy({ highWaterMark });
|
||||||
|
}
|
||||||
|
|
||||||
|
// When not running in objectMode explicitly, we just fall
|
||||||
|
// back to a minimal strategy that just specifies the highWaterMark
|
||||||
|
// and no size algorithm. Using a ByteLengthQueuingStrategy here
|
||||||
|
// is unnecessary.
|
||||||
|
return { highWaterMark };
|
||||||
|
};
|
||||||
|
|
||||||
|
const strategy = evaluateStrategyOrFallback(options?.strategy);
|
||||||
|
|
||||||
let controller;
|
let controller;
|
||||||
|
|
||||||
|
75
test/parallel/test-stream-readable-strategy-option.js
Normal file
75
test/parallel/test-stream-readable-strategy-option.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const { Readable } = require('stream');
|
||||||
|
const assert = require('assert');
|
||||||
|
const { strictEqual } = require('assert');
|
||||||
|
|
||||||
|
{
|
||||||
|
// Strategy 2
|
||||||
|
const streamData = ['a', 'b', 'c', null];
|
||||||
|
|
||||||
|
// Fulfill a Readable object
|
||||||
|
const readable = new Readable({
|
||||||
|
read: common.mustCall(() => {
|
||||||
|
process.nextTick(() => {
|
||||||
|
readable.push(streamData.shift());
|
||||||
|
});
|
||||||
|
}, streamData.length),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use helper to convert it to a Web ReadableStream using ByteLength strategy
|
||||||
|
const readableStream = Readable.toWeb(readable, {
|
||||||
|
strategy: new ByteLengthQueuingStrategy({ highWaterMark: 1 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(!readableStream.locked);
|
||||||
|
readableStream.getReader().read().then(common.mustCall());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Strategy 2
|
||||||
|
const streamData = ['a', 'b', 'c', null];
|
||||||
|
|
||||||
|
// Fulfill a Readable object
|
||||||
|
const readable = new Readable({
|
||||||
|
read: common.mustCall(() => {
|
||||||
|
process.nextTick(() => {
|
||||||
|
readable.push(streamData.shift());
|
||||||
|
});
|
||||||
|
}, streamData.length),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use helper to convert it to a Web ReadableStream using Count strategy
|
||||||
|
const readableStream = Readable.toWeb(readable, {
|
||||||
|
strategy: new CountQueuingStrategy({ highWaterMark: 1 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(!readableStream.locked);
|
||||||
|
readableStream.getReader().read().then(common.mustCall());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const desireSizeExpected = 2;
|
||||||
|
|
||||||
|
const stringStream = new ReadableStream(
|
||||||
|
{
|
||||||
|
start(controller) {
|
||||||
|
// Check if the strategy is being assigned on the init of the ReadableStream
|
||||||
|
strictEqual(controller.desiredSize, desireSizeExpected);
|
||||||
|
controller.enqueue('a');
|
||||||
|
controller.enqueue('b');
|
||||||
|
controller.close();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new CountQueuingStrategy({ highWaterMark: desireSizeExpected })
|
||||||
|
);
|
||||||
|
|
||||||
|
const reader = stringStream.getReader();
|
||||||
|
|
||||||
|
reader.read().then(common.mustCall());
|
||||||
|
reader.read().then(common.mustCall());
|
||||||
|
reader.read().then(({ value, done }) => {
|
||||||
|
strictEqual(value, undefined);
|
||||||
|
strictEqual(done, true);
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user