diff --git a/lib/internal/abort_controller.js b/lib/internal/abort_controller.js index 2fba1e3fdbe81b..cc6c56f89f9558 100644 --- a/lib/internal/abort_controller.js +++ b/lib/internal/abort_controller.js @@ -4,6 +4,7 @@ // in https://github.com/mysticatea/abort-controller (MIT license) const { + ArrayPrototypePush, ObjectAssign, ObjectDefineProperties, ObjectDefineProperty, @@ -373,17 +374,36 @@ ObjectDefineProperty(AbortSignal.prototype, SymbolToStringTag, { defineEventHandler(AbortSignal.prototype, 'abort'); function abortSignal(signal, reason) { + // 1. If signal is aborted, then return. if (signal[kAborted]) return; signal[kAborted] = true; + // 2. Set signal's abort reason to reason if it is given; + // otherwise to a new "AbortError" DOMException. signal[kReason] = reason; + // 3. Let dependentSignalsToAbort be a new list. + const dependentSignalsToAbort = []; + // 4. For each dependentSignal of signal's dependent signals: + signal[kDependantSignals]?.forEach((s) => { + const dependentSignal = s.deref(); + // 1. If dependentSignal is not aborted, then: + if (dependentSignal && !dependentSignal[kAborted]) { + // 1. Set dependentSignal's abort reason to signal's abort reason. + dependentSignal[kReason] = reason; + // 2. Append dependentSignal to dependentSignalsToAbort. + ArrayPrototypePush(dependentSignalsToAbort, dependentSignal); + } + }); + // 5. Run the abort steps for signal const event = new Event('abort', { [kTrustEvent]: true, }); signal.dispatchEvent(event); - signal[kDependantSignals]?.forEach((s) => { - const signalRef = s.deref(); - if (signalRef) abortSignal(signalRef, reason); - }); + // 6. For each dependentSignal of dependentSignalsToAbort, + // run the abort steps for dependentSignal. + for (let i = 0; i < dependentSignalsToAbort.length; i++) { + const dependentSignal = dependentSignalsToAbort[i]; + if (dependentSignal) abortSignal(dependentSignal, reason); + }; } class AbortController {