Skip to content

Commit 29ce707

Browse files
jasnelladuh95
authored andcommitted
stream: ensure factory signals remain active through closing
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode PR-URL: #65658 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
1 parent c4a1726 commit 29ce707

3 files changed

Lines changed: 21 additions & 2 deletions

File tree

doc/api/stream_iter.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,9 @@ added: v25.9.0
769769
**Default:** `16384`.
770770
* `backpressure` {string} Backpressure policy: `'strict'`, `'unbounded'`,
771771
`'drop-oldest'`, or `'drop-newest'`. **Default:** `'strict'`.
772-
* `signal` {AbortSignal} Abort the stream.
772+
* `signal` {AbortSignal} Abort the stream. The signal remains active while
773+
buffered data drains after `writer.end()`; aborting during that time fails
774+
the writer and rejects the pending `end()` promise.
773775
* Returns: {Object}
774776
* `writer` {Writable} The writer side.
775777
* `readable` {AsyncIterable} whose chunks fulfill with {Uint8Array\[]}

lib/internal/streams/iter/push.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,14 +334,14 @@ class PushQueue {
334334
return this.#bytesWritten; // Idempotent
335335
}
336336

337-
this.#cleanup();
338337
this.#rejectPendingWrites(
339338
new ERR_INVALID_STATE.TypeError('Writer closed'));
340339
this.#resolvePendingDrains(false);
341340

342341
// If buffer is empty, close immediately
343342
if (this.#slots.length === 0) {
344343
this.#writerState = 'closed';
344+
this.#cleanup();
345345
this.#resolvePendingReads();
346346
return this.#bytesWritten;
347347
}
@@ -359,6 +359,7 @@ class PushQueue {
359359
endDrained() {
360360
if (this.#writerState !== 'closing') return;
361361
this.#writerState = 'closed';
362+
this.#cleanup();
362363
if (this.#pendingEnd) {
363364
this.#pendingEnd.resolve(this.#bytesWritten);
364365
this.#pendingEnd = null;

test/parallel/test-stream-iter-push-writer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,21 @@ async function testEndSignalAbortWhileDraining() {
324324
assert.strictEqual(await completedEnd, 5);
325325
}
326326

327+
async function testFactorySignalAbortWhileDraining() {
328+
const controller = new AbortController();
329+
const reason = new Error('stream aborted while draining');
330+
const { writer, readable } = push({ signal: controller.signal });
331+
332+
writer.writeSync('hello');
333+
const end = writer.end();
334+
const endRejected = assert.rejects(end, (error) => error === reason);
335+
controller.abort(reason);
336+
337+
await endRejected;
338+
await assert.rejects(text(readable), (error) => error === reason);
339+
await assert.rejects(writer.end(), (error) => error === reason);
340+
}
341+
327342
async function testEndAfterEndSyncWaitsForDrain() {
328343
const { writer, readable } = push();
329344
writer.writeSync('hello');
@@ -634,6 +649,7 @@ Promise.all([
634649
testEndAsyncReturnValue(),
635650
testEndWithPreAbortedSignal(),
636651
testEndSignalAbortWhileDraining(),
652+
testFactorySignalAbortWhileDraining(),
637653
testEndAfterEndSyncWaitsForDrain(),
638654
testWriteUint8Array(),
639655
testOndrainWaitsForDrain(),

0 commit comments

Comments
 (0)