|
4 | 4 | // in https://github.com/mysticatea/abort-controller (MIT license)
|
5 | 5 |
|
6 | 6 | const {
|
| 7 | + ArrayPrototypePush, |
7 | 8 | ObjectAssign,
|
8 | 9 | ObjectDefineProperties,
|
9 | 10 | ObjectDefineProperty,
|
10 | 11 | PromiseResolve,
|
11 | 12 | SafeFinalizationRegistry,
|
12 | 13 | SafeSet,
|
| 14 | + SetPrototypeForEach, |
13 | 15 | Symbol,
|
14 | 16 | SymbolToStringTag,
|
15 | 17 | WeakRef,
|
@@ -372,18 +374,50 @@ ObjectDefineProperty(AbortSignal.prototype, SymbolToStringTag, {
|
372 | 374 |
|
373 | 375 | defineEventHandler(AbortSignal.prototype, 'abort');
|
374 | 376 |
|
| 377 | +// https://dom.spec.whatwg.org/#dom-abortsignal-abort |
375 | 378 | function abortSignal(signal, reason) {
|
| 379 | + // 1. If signal is aborted, then return. |
376 | 380 | if (signal[kAborted]) return;
|
| 381 | + |
| 382 | + // 2. Set signal's abort reason to reason if it is given; |
| 383 | + // otherwise to a new "AbortError" DOMException. |
377 | 384 | signal[kAborted] = true;
|
378 | 385 | signal[kReason] = reason;
|
| 386 | + // 3. Let dependentSignalsToAbort be a new list. |
| 387 | + const dependentSignalsToAbort = []; |
| 388 | + // 4. For each dependentSignal of signal's dependent signals: |
| 389 | + if (signal[kDependantSignals]) { |
| 390 | + SetPrototypeForEach(signal[kDependantSignals], (s) => { |
| 391 | + const dependentSignal = s.deref(); |
| 392 | + // 1. If dependentSignal is not aborted, then: |
| 393 | + if (dependentSignal && !dependentSignal[kAborted]) { |
| 394 | + // 1. Set dependentSignal's abort reason to signal's abort reason. |
| 395 | + dependentSignal[kReason] = reason; |
| 396 | + dependentSignal[kAborted] = true; |
| 397 | + // 2. Append dependentSignal to dependentSignalsToAbort. |
| 398 | + ArrayPrototypePush(dependentSignalsToAbort, dependentSignal); |
| 399 | + } |
| 400 | + }); |
| 401 | + } |
| 402 | + // 5. Run the abort steps for signal |
| 403 | + runAbort(signal); |
| 404 | + // 6. For each dependentSignal of dependentSignalsToAbort, |
| 405 | + // run the abort steps for dependentSignal. |
| 406 | + for (let i = 0; i < dependentSignalsToAbort.length; i++) { |
| 407 | + const dependentSignal = dependentSignalsToAbort[i]; |
| 408 | + runAbort(dependentSignal); |
| 409 | + }; |
| 410 | +} |
| 411 | + |
| 412 | +// To run the abort steps for an AbortSignal signal |
| 413 | +function runAbort(signal) { |
| 414 | + // TODO(jazelly): 1. For each algorithm of signal's abort algorithms: run algorithm. |
| 415 | + // TODO(jazelly): 2. Empty signal's abort algorithms. |
| 416 | + // 3. Fire an event named abort at signal. |
379 | 417 | const event = new Event('abort', {
|
380 | 418 | [kTrustEvent]: true,
|
381 | 419 | });
|
382 | 420 | signal.dispatchEvent(event);
|
383 |
| - signal[kDependantSignals]?.forEach((s) => { |
384 |
| - const signalRef = s.deref(); |
385 |
| - if (signalRef) abortSignal(signalRef, reason); |
386 |
| - }); |
387 | 421 | }
|
388 | 422 |
|
389 | 423 | class AbortController {
|
|
0 commit comments