Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
stream: fix recursive WritableStream abort
Recheck the stream state after signaling abort, as required by steps 3
and 4 of the WritableStreamAbort algorithm.

Only reject pending close promise caches, as a cache materialized after
the stream becomes errored may already contain a rejected promise.

This makes the recursive abort WPT pass and removes its expected-failure
entry.

Refs: https://streams.spec.whatwg.org/#writable-stream-abort
Signed-off-by: Jeong SeokChan <starp321@naver.com>
  • Loading branch information
standard-Chan committed Jul 29, 2026
commit 84727d9065f79349ed0cb79f0a55007c7e15f40f
15 changes: 9 additions & 6 deletions lib/internal/webstreams/writablestream.js
Original file line number Diff line number Diff line change
Expand Up @@ -701,15 +701,18 @@ function writerReadyPromise(writer) {
}

function writableStreamAbort(stream, reason) {
const {
state,
controller,
} = stream[kState];
const { controller } = stream[kState];

let state = stream[kState].state;
if (state === 'closed' || state === 'errored')
return PromiseResolve();

controller[kState].abortController.abort(reason);

state = stream[kState].state;
if (state === 'closed' || state === 'errored')
return PromiseResolve();

if (stream[kState].pendingAbortRequest.abort.promise !== undefined)
return stream[kState].pendingAbortRequest.abort.promise;

Expand Down Expand Up @@ -807,7 +810,7 @@ function writableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
}

const closedPromiseCache = stream[kState].closedPromise;
if (closedPromiseCache !== undefined) {
if (closedPromiseCache !== undefined && isPromisePending(closedPromiseCache.promise)) {
setPromiseHandled(closedPromiseCache.promise);
closedPromiseCache.reject(stream[kState].storedError);
}
Expand All @@ -817,7 +820,7 @@ function writableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
} = stream[kState];
if (writer !== undefined) {
const closeCache = writer[kState].close;
if (closeCache !== undefined) {
if (closeCache !== undefined && isPromisePending(closeCache.promise)) {
setPromiseHandled(closeCache.promise);
closeCache.reject(stream[kState].storedError);
}
Expand Down
8 changes: 0 additions & 8 deletions test/wpt/status/streams.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,5 @@
},
"transform-streams/invalid-realm.tentative.window.js": {
"skip": "Browser-specific test"
},
"writable-streams/aborting.any.js": {
"fail": {
"note": "Recursive abort() call from within an abort algorithm triggers ERR_INTERNAL_ASSERTION",
"expected": [
"recursive abort() call from abort() aborting signal"
]
}
}
}
Loading