From 9f5022be915d8a4ce5338d4c90f2c5d06b4f5a7f Mon Sep 17 00:00:00 2001 From: bellbind Date: Wed, 26 Jul 2023 22:24:02 +0900 Subject: [PATCH 1/2] lib: fix to add resolve() before return at Blob.stream()'s source.pull() Add lacked calling resolve() for finish ReadableStream source.pull(). Fixes: https://github.com/nodejs/node/issues/48668 Fixes: https://github.com/nodejs/node/issues/48916 Fixes: https://github.com/nodejs/node/issues/48232 Refs: https://github.com/nodejs/node/commit/8cc14387a2e77d7a2b411e7edaed690d43ea3809 --- lib/internal/blob.js | 5 +++++ test/parallel/test-blob.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 655023e07780f2..c5b417ddc291b6 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -360,6 +360,11 @@ class Blob { queueMicrotask(() => { if (c.desiredSize <= 0) { // A manual backpressure check. + if (this.pendingPulls.length !== 0) { + // A case of waiting pull finished (= not yet canceled) + const pending = this.pendingPulls.shift(); + pending.resolve(); + } return; } readNext(); diff --git a/test/parallel/test-blob.js b/test/parallel/test-blob.js index 27dee5690d7e06..fdd4d239edc1f5 100644 --- a/test/parallel/test-blob.js +++ b/test/parallel/test-blob.js @@ -269,6 +269,29 @@ assert.throws(() => new Blob({}), { reader.closed.then(common.mustCall()); })().then(common.mustCall()); +(async () => { + const b = new Blob(['A', 'B', 'C']); + const stream = b.stream(); + const chunks = []; + const decoder = new TextDecoder(); + await stream.pipeTo(new WritableStream({ + write(chunk) { + chunks.push(decoder.decode(chunk, { stream: true })); + } + })); + assert.strictEqual(chunks.join(''), 'ABC'); +})().then(common.mustCall()); + +(async () => { + const file = new Blob([''], { type: 'image/svg+xml' }); + const url = URL.createObjectURL(file); + const res = await fetch(url); + const blob = await res.blob(); + assert.strictEqual(blob.size, 11); + assert.strictEqual(blob.type, 'image/svg+xml'); + assert.strictEqual(await blob.text(), ''); +})().then(common.mustCall()); + (async () => { const b = new Blob(Array(10).fill('hello')); const stream = b.stream(); From dba96155a1f17283bf23761fda5bc879a5c6b808 Mon Sep 17 00:00:00 2001 From: Debadree Chatterjee Date: Fri, 11 Aug 2023 23:34:30 +0530 Subject: [PATCH 2/2] fixup! test only if crypto is present and an additional test from bug report --- test/parallel/test-blob.js | 49 ++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/test/parallel/test-blob.js b/test/parallel/test-blob.js index fdd4d239edc1f5..a517bad1ccb42d 100644 --- a/test/parallel/test-blob.js +++ b/test/parallel/test-blob.js @@ -283,13 +283,48 @@ assert.throws(() => new Blob({}), { })().then(common.mustCall()); (async () => { - const file = new Blob([''], { type: 'image/svg+xml' }); - const url = URL.createObjectURL(file); - const res = await fetch(url); - const blob = await res.blob(); - assert.strictEqual(blob.size, 11); - assert.strictEqual(blob.type, 'image/svg+xml'); - assert.strictEqual(await blob.text(), ''); + const b = new Blob(['A', 'B', 'C']); + const stream = b.stream(); + const chunks = []; + const decoder = new TextDecoder(); + await stream.pipeTo( + new WritableStream({ + write(chunk) { + chunks.push(decoder.decode(chunk, { stream: true })); + }, + }) + ); + assert.strictEqual(chunks.join(''), 'ABC'); +})().then(common.mustCall()); + +(async () => { + // Ref: https://github.com/nodejs/node/issues/48668 + const chunks = []; + const stream = new Blob(['Hello world']).stream(); + const decoder = new TextDecoder(); + await Promise.resolve(); + await stream.pipeTo( + new WritableStream({ + write(chunk) { + chunks.push(decoder.decode(chunk, { stream: true })); + }, + }) + ); + assert.strictEqual(chunks.join(''), 'Hello world'); +})().then(common.mustCall()); + +(async () => { + // Ref: https://github.com/nodejs/node/issues/48668 + if (common.hasCrypto) { + // Can only do this test if we have node built with crypto + const file = new Blob([''], { type: 'image/svg+xml' }); + const url = URL.createObjectURL(file); + const res = await fetch(url); + const blob = await res.blob(); + assert.strictEqual(blob.size, 11); + assert.strictEqual(blob.type, 'image/svg+xml'); + assert.strictEqual(await blob.text(), ''); + } })().then(common.mustCall()); (async () => {