Skip to content

Observe the pipe's AbortSignal through an abort algorithm - #7500

Merged
jasnell merged 1 commit into
mainfrom
jasnell/ts-streams-pipe-abort-algorithm
Sep 24, 2026
Merged

jasnell merged 1 commit into
mainfrom
jasnell/ts-streams-pipe-abort-algorithm

Conversation

@jasnell

@jasnell jasnell commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

The TS pipe watched its signal with an 'abort' event listener. A synthetic dispatchEvent(new Event('abort')) on a live signal aborted the pipe with an undefined reason, and an earlier user listener calling stopImmediatePropagation() kept the abort from the pipe, which hung.

The pipe now registers a DOM abort algorithm, which runs before the event's listeners and only for a real abort. The bootstrap reaches AbortSignal::addAbortAlgorithm() through a new utils.addAbortAlgorithm, which returns an AbortAlgorithmHandle; the pipe removes the algorithm when it settles. The handle type is internal: not on the global scope and excluded from the generated types.

Parity with C++. Behind the experimental typescript_implemented_streams flag.

The TS pipe watched its signal with an 'abort' event listener. A
synthetic dispatchEvent(new Event('abort')) on a live signal aborted the
pipe with an undefined reason, and an earlier user listener calling
stopImmediatePropagation() kept the abort from the pipe, which hung.

The pipe now registers a DOM abort algorithm, which runs before the
event's listeners and only for a real abort. The bootstrap reaches
AbortSignal::addAbortAlgorithm() through a new utils.addAbortAlgorithm,
which returns an AbortAlgorithmHandle; the pipe removes the algorithm
when it settles. The handle type is internal: not on the global scope
and excluded from the generated types.

Parity with C++. Behind the experimental typescript_implemented_streams
flag.
@jasnell
jasnell requested review from guybedford and npaun September 24, 2026 17:17
@jasnell
jasnell requested review from a team as code owners September 24, 2026 17:17
@ask-bonk

ask-bonk Bot commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally: piping-ts@, piping-cpp@ and basics-test@ pass, and with readable.ts reverted to main both syntheticAbortEventIgnored and stopImmediatePropagationDoesNotBlockAbort fail, so the regression coverage is real. Handle lifetime looks right: the registration stays reachable through the signal's traced algorithm list while it matters, and unregistering from a collected wrapper follows the existing EventHandler.abortHandler pattern.

One non-blocking note: this is the first path that runs a JS function inside runAbortSteps. Checked with a scratch test: an algorithm that throws propagates out of abort(), the remaining algorithms never run (the list is already cleared), native cancellations and the 'abort' event are skipped, while the signal stays aborted. The pipe's algorithm can't throw synchronously today, so this is fine as is, but the addAbortAlgorithmForBootstrap wrapper is the natural place to either catch and report or to state "must not throw" in the utils.addAbortAlgorithm contract. Follow-up is fine.

@jasnell
jasnell merged commit 8f21ea8 into main Sep 24, 2026
26 of 27 checks passed
@jasnell
jasnell deleted the jasnell/ts-streams-pipe-abort-algorithm branch September 24, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants