* @typedef {import('./queuingstrategies').QueuingStrategy} QueuingStrategy * @param {Readable} streamReadable * @param {{ * strategy? : QueuingStrategy * type? : 'bytes', * }} [options] * @returns {ReadableStream}
(streamReadable, options = kEmptyObject)
| 468 | * @returns {ReadableStream} |
| 469 | */ |
| 470 | function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObject) { |
| 471 | // Not using the internal/streams/utils isReadableNodeStream utility |
| 472 | // here because it will return false if streamReadable is a Duplex |
| 473 | // whose readable option is false. For a Duplex that is not readable, |
| 474 | // we want it to pass this check but return a closed ReadableStream. |
| 475 | if (typeof streamReadable?._readableState !== 'object') { |
| 476 | throw new ERR_INVALID_ARG_TYPE( |
| 477 | 'streamReadable', |
| 478 | 'stream.Readable', |
| 479 | streamReadable); |
| 480 | } |
| 481 | validateObject(options, 'options'); |
| 482 | if (options.type !== undefined) { |
| 483 | validateOneOf(options.type, 'options.type', ['bytes', undefined]); |
| 484 | } |
| 485 | |
| 486 | const isBYOB = options.type === 'bytes'; |
| 487 | let controller; |
| 488 | let wasCanceled = false; |
| 489 | let strategy; |
| 490 | |
| 491 | /** @type {UnderlyingSource} */ |
| 492 | const underlyingSource = { |
| 493 | __proto__: null, |
| 494 | type: isBYOB ? 'bytes' : undefined, |
| 495 | start(c) { controller = c; }, |
| 496 | cancel(reason) { |
| 497 | wasCanceled = true; |
| 498 | destroy(streamReadable, reason); |
| 499 | }, |
| 500 | }; |
| 501 | |
| 502 | const readable = isReadable(streamReadable); |
| 503 | const objectMode = streamReadable.readableObjectMode; |
| 504 | if (readable) { |
| 505 | underlyingSource.pull = function pull() { |
| 506 | streamReadable.resume(); |
| 507 | }; |
| 508 | |
| 509 | const highWaterMark = streamReadable.readableHighWaterMark; |
| 510 | strategy = isBYOB ? { highWaterMark } : |
| 511 | options.strategy ?? new (objectMode ? CountQueuingStrategy : ByteLengthQueuingStrategy)({ highWaterMark }); |
| 512 | } |
| 513 | const readableStream = new ReadableStream(underlyingSource, strategy); |
| 514 | |
| 515 | // When adapting a Duplex as a ReadableStream, readable completion should not |
| 516 | // wait for a half-open writable side to finish as well. |
| 517 | let cleanup = noop; |
| 518 | cleanup = eos(streamReadable, { |
| 519 | __proto__: null, |
| 520 | writable: false, |
| 521 | [kEosNodeSynchronousCallback]: true, |
| 522 | }, (error) => { |
| 523 | error = handleKnownInternalErrors(error); |
| 524 | |
| 525 | // If eos calls the callback synchronously, cleanup is still a no-op here. |
| 526 | cleanup(); |
| 527 |
no test coverage detected
searching dependent graphs…