From 273ae636f579ae3f8b63985702abe4e28382b1dd Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Wed, 27 May 2026 17:27:50 -0700 Subject: [PATCH] stream: settle pending broadcast reads on return Resolve pending next() calls when broadcast consumers are returned, so the promise does not remain pending after iterator cleanup. Fixes: https://github.com/nodejs/node/issues/63519 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 --- lib/internal/streams/iter/broadcast.js | 1 + test/parallel/test-stream-iter-broadcast-basic.js | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/internal/streams/iter/broadcast.js b/lib/internal/streams/iter/broadcast.js index e6a404729d6e0b..aa83c9636598ea 100644 --- a/lib/internal/streams/iter/broadcast.js +++ b/lib/internal/streams/iter/broadcast.js @@ -165,6 +165,7 @@ class BroadcastImpl { function detach() { state.detached = true; + state.resolve?.({ __proto__: null, done: true, value: undefined }); state.resolve = null; state.reject = null; if (self.#deleteConsumer(state)) { diff --git a/test/parallel/test-stream-iter-broadcast-basic.js b/test/parallel/test-stream-iter-broadcast-basic.js index ab2c81304ec2ac..32c1750fb4cbfd 100644 --- a/test/parallel/test-stream-iter-broadcast-basic.js +++ b/test/parallel/test-stream-iter-broadcast-basic.js @@ -161,6 +161,18 @@ async function testCancelWithReason() { assert.strictEqual(result.message, 'cancelled'); } +async function testPendingNextSettlesAfterReturn() { + const { broadcast: bc } = broadcast(); + const iter = bc.push()[Symbol.asyncIterator](); + + const pendingNext = iter.next(); + await iter.return(); + + const result = await pendingNext; + assert.strictEqual(result.done, true); + assert.strictEqual(result.value, undefined); +} + // ============================================================================= // Writer fail detaches consumers // ============================================================================= @@ -254,6 +266,7 @@ Promise.all([ testCancelWithoutReason(), testCancelWithReason(), testCancelWithFalsyReason(), + testPendingNextSettlesAfterReturn(), testFailDetachesConsumers(), testWriterFailIdempotent(), testLateJoinerSeesBufferedData(),