From c12600dca41f30cf0368c1e8a8c2932edd09950a Mon Sep 17 00:00:00 2001 From: Jason Zhang Date: Sun, 22 Sep 2024 22:15:01 +0930 Subject: [PATCH] stream: set stream prototype to closest transferable superclass --- lib/internal/webstreams/readablestream.js | 3 +++ lib/internal/webstreams/transformstream.js | 1 + lib/internal/webstreams/writablestream.js | 2 ++ test/parallel/test-structuredClone-global.js | 14 ++++++++++++++ 4 files changed, 20 insertions(+) diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 94c76a83898222..7279ff3de4b28b 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -639,6 +639,7 @@ ObjectDefineProperties(ReadableStream, { }); function InternalTransferredReadableStream() { + ObjectSetPrototypeOf(this, ReadableStream.prototype); markTransferMode(this, false, true); this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); @@ -1226,6 +1227,7 @@ ObjectDefineProperties(ReadableByteStreamController.prototype, { }); function InternalReadableStream(start, pull, cancel, highWaterMark, size) { + ObjectSetPrototypeOf(this, ReadableStream.prototype); markTransferMode(this, false, true); this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); @@ -1253,6 +1255,7 @@ function createReadableStream(start, pull, cancel, highWaterMark = 1, size = () } function InternalReadableByteStream(start, pull, cancel) { + ObjectSetPrototypeOf(this, ReadableStream.prototype); markTransferMode(this, false, true); this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); diff --git a/lib/internal/webstreams/transformstream.js b/lib/internal/webstreams/transformstream.js index 68b1e7aa83d9fc..9e26387b3b6110 100644 --- a/lib/internal/webstreams/transformstream.js +++ b/lib/internal/webstreams/transformstream.js @@ -256,6 +256,7 @@ ObjectDefineProperties(TransformStream.prototype, { }); function InternalTransferredTransformStream() { + ObjectSetPrototypeOf(this, TransformStream.prototype); markTransferMode(this, false, true); this[kType] = 'TransformStream'; this[kState] = { diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index 43f7a5121b1e97..ba1461fc70e95f 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -300,6 +300,7 @@ ObjectDefineProperties(WritableStream.prototype, { }); function InternalTransferredWritableStream() { + ObjectSetPrototypeOf(this, WritableStream.prototype); markTransferMode(this, false, true); this[kType] = 'WritableStream'; this[kState] = createWritableStreamState(); @@ -516,6 +517,7 @@ ObjectDefineProperties(WritableStreamDefaultController.prototype, { }); function InternalWritableStream(start, write, close, abort, highWaterMark, size) { + ObjectSetPrototypeOf(this, WritableStream.prototype); markTransferMode(this, false, true); this[kType] = 'WritableStream'; this[kState] = createWritableStreamState(); diff --git a/test/parallel/test-structuredClone-global.js b/test/parallel/test-structuredClone-global.js index 52a73cd2ae7c8f..50fcf6047828a8 100644 --- a/test/parallel/test-structuredClone-global.js +++ b/test/parallel/test-structuredClone-global.js @@ -16,6 +16,20 @@ assert.strictEqual(structuredClone(undefined, null), undefined); assert.strictEqual(structuredClone(undefined, { transfer: null }), undefined); assert.strictEqual(structuredClone(undefined, { }), undefined); +// Transferables or its subclasses should be received with its closest transferable superclass +for (const StreamClass of [ReadableStream, WritableStream, TransformStream]) { + const original = new StreamClass(); + const transfer = structuredClone(original, { transfer: [original] }); + assert.strictEqual(Object.getPrototypeOf(transfer), StreamClass.prototype); + assert.ok(transfer instanceof StreamClass); + + const extended = class extends StreamClass {}; + const extendedOriginal = new extended(); + const extendedTransfer = structuredClone(extendedOriginal, { transfer: [extendedOriginal] }); + assert.strictEqual(Object.getPrototypeOf(extendedTransfer), StreamClass.prototype); + assert.ok(extendedTransfer instanceof StreamClass); +} + { // See: https://github.com/nodejs/node/issues/49940 const cloned = structuredClone({}, {