Skip to content

Commit b886551

Browse files
CCR 6
Install the abort listener before dispatching a factory operation. `awaitFactoryOperation` evaluated `operation()` as the first element of the race, so the listener was only attached afterwards. The window is synchronous and hard to hit in practice, but it does not need to exist: an abort raised while the thunk is starting would find no listener and the race would then wait on an operation whose run had already been cancelled. The listener is now attached first, and the aborted check moved after it, so the ordering guarantees both properties directly — no abort can be missed, and an already-aborted run still never dispatches.
1 parent 85a443e commit b886551

1 file changed

Lines changed: 9 additions & 8 deletions

File tree

nodejs/src/session.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -312,18 +312,19 @@ async function awaitFactoryOperation<TResult>(
312312
): Promise<TResult> {
313313
// The operation is a thunk so an already-aborted run never dispatches the
314314
// RPC at all, rather than sending it and rejecting locally afterwards.
315-
throwIfFactoryAborted(signal);
316315
let rejectAbort: ((reason?: unknown) => void) | undefined;
316+
const abortPromise = new Promise<never>((_resolve, reject) => {
317+
rejectAbort = reject;
318+
});
317319
const onAbort = () =>
318320
rejectAbort?.(signal.reason ?? new DOMException("Factory run was aborted", "AbortError"));
321+
// Register before the abort check and before dispatching, so an abort can
322+
// neither be missed by a not-yet-attached listener nor start work on an
323+
// already-cancelled run.
324+
signal.addEventListener("abort", onAbort, { once: true });
319325
try {
320-
return await Promise.race([
321-
operation(),
322-
new Promise<never>((_resolve, reject) => {
323-
rejectAbort = reject;
324-
signal.addEventListener("abort", onAbort, { once: true });
325-
}),
326-
]);
326+
throwIfFactoryAborted(signal);
327+
return await Promise.race([operation(), abortPromise]);
327328
} finally {
328329
signal.removeEventListener("abort", onAbort);
329330
}

0 commit comments

Comments
 (0)