stream: reject closed only after sink abort settles

Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65727
Fixes: https://github.com/nodejs/node/issues/65726
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
This commit is contained in:
Lazizbek Ergashev authored and GitHub committed 2026-09-12 11:01:37 +00:00
1 parent 1278496599
commit 50b355ec04
2 files changed
+49

No files matched your search

@@ -928,6 +928,13 @@ function writableStreamFinishErroring(stream) {
writableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
return;
}
// The closed promises are only rejected once the sink's abort algorithm
// settles, so materialize them here: deriving them from the 'errored'
// state within that window would hand out an already rejected promise.
stream[kState].closedPromise ??= PromiseWithResolvers();
const writer = stream[kState].writer;
if (writer !== undefined)
writer[kState].close ??= PromiseWithResolvers();
PromisePrototypeThen(
stream[kState].controller[kAbort](abortRequest.reason),
() => {
@@ -0,0 +1,42 @@
'use strict';
// The writer's closed promise stays pending until the sink's abort()
// algorithm settles, even when it is first observed after the stream has
// already reached the 'errored' state.
const common = require('../common');
const assert = require('assert');
const { setImmediate: immediate } = require('timers/promises');
const { WritableStream } = require('stream/web');
async function main() {
const error = new Error('boom');
const { promise: abortComplete, resolve: finishAbort } = Promise.withResolvers();
const ws = new WritableStream({
abort: common.mustCall((reason) => {
assert.strictEqual(reason, error);
return abortComplete;
}),
});
const writer = ws.getWriter();
const aborted = writer.abort(error);
// Lets the stream finish erroring and call the sink's abort().
await immediate();
let closedSettled = false;
const closed = writer.closed.catch(common.mustCall((reason) => {
closedSettled = true;
assert.strictEqual(reason, error);
}));
await immediate();
assert.strictEqual(closedSettled, false);
finishAbort();
await aborted;
await closed;
assert.strictEqual(closedSettled, true);
}
main().then(common.mustCall());