From ee4fc7d78ca4069e3d9c1dbd12c85b6d89931e69 Mon Sep 17 00:00:00 2001 From: Khafra Date: Sat, 26 Aug 2023 07:43:58 -0400 Subject: [PATCH] stream: use Buffer.from when constructor is a Buffer When using BYOB streams, it's possible for the constructor in readableByteStreamControllerConvertPullIntoDescriptor to be a node Buffer. If it is, use `Buffer.from` over `new ctor`. Fixes https://github.com/nodejs/node/issues/49245 PR-URL: https://github.com/nodejs/node/pull/49250 Reviewed-By: Debadree Chatterjee Reviewed-By: LiviaMedeiros Reviewed-By: Yagiz Nizipli --- lib/internal/webstreams/readablestream.js | 7 +++ .../test-whatwg-readablebytestreambyob.js | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 test/parallel/test-whatwg-readablebytestreambyob.js diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 99e6ad5a0ba925..2f1eb6cc8e6c8c 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -130,6 +130,8 @@ const { writableStreamDefaultWriterWrite, } = require('internal/webstreams/writablestream'); +const { Buffer } = require('buffer'); + const assert = require('internal/assert'); const kCancel = Symbol('kCancel'); @@ -1846,6 +1848,11 @@ function readableByteStreamControllerConvertPullIntoDescriptor(desc) { throw new ERR_INVALID_STATE.RangeError('The buffer size is invalid'); assert(!(bytesFilled % elementSize)); const transferredBuffer = transferArrayBuffer(buffer); + + if (ctor === Buffer) { + return Buffer.from(transferredBuffer, byteOffset, bytesFilled / elementSize); + } + return new ctor(transferredBuffer, byteOffset, bytesFilled / elementSize); } diff --git a/test/parallel/test-whatwg-readablebytestreambyob.js b/test/parallel/test-whatwg-readablebytestreambyob.js new file mode 100644 index 00000000000000..5dbe4813dbc4f6 --- /dev/null +++ b/test/parallel/test-whatwg-readablebytestreambyob.js @@ -0,0 +1,62 @@ +'use strict'; + +const common = require('../common'); + +const { + open, +} = require('fs/promises'); + +const { + Buffer, +} = require('buffer'); + +class Source { + async start(controller) { + this.file = await open(__filename); + this.controller = controller; + } + + async pull(controller) { + const byobRequest = controller.byobRequest; + const view = byobRequest.view; + + const { + bytesRead, + } = await this.file.read({ + buffer: view, + offset: view.byteOffset, + length: view.byteLength + }); + + if (bytesRead === 0) { + await this.file.close(); + this.controller.close(); + } + + byobRequest.respond(bytesRead); + } + + get type() { return 'bytes'; } + + get autoAllocateChunkSize() { return 1024; } +} + +(async () => { + const source = new Source(); + const stream = new ReadableStream(source); + + const { emitWarning } = process; + + process.emitWarning = common.mustNotCall(); + + try { + const reader = stream.getReader({ mode: 'byob' }); + + let result; + do { + result = await reader.read(Buffer.alloc(100)); + } while (!result.done); + } finally { + process.emitWarning = emitWarning; + } +})().then(common.mustCall());