11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci// Modeled very closely on the AbortController implementation
41cb0ef41Sopenharmony_ci// in https://github.com/mysticatea/abort-controller (MIT license)
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst {
71cb0ef41Sopenharmony_ci  ObjectAssign,
81cb0ef41Sopenharmony_ci  ObjectDefineProperties,
91cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
101cb0ef41Sopenharmony_ci  ObjectDefineProperty,
111cb0ef41Sopenharmony_ci  PromiseResolve,
121cb0ef41Sopenharmony_ci  SafeFinalizationRegistry,
131cb0ef41Sopenharmony_ci  SafeSet,
141cb0ef41Sopenharmony_ci  Symbol,
151cb0ef41Sopenharmony_ci  SymbolToStringTag,
161cb0ef41Sopenharmony_ci  WeakRef,
171cb0ef41Sopenharmony_ci} = primordials;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst {
201cb0ef41Sopenharmony_ci  defineEventHandler,
211cb0ef41Sopenharmony_ci  EventTarget,
221cb0ef41Sopenharmony_ci  Event,
231cb0ef41Sopenharmony_ci  kTrustEvent,
241cb0ef41Sopenharmony_ci  kNewListener,
251cb0ef41Sopenharmony_ci  kRemoveListener,
261cb0ef41Sopenharmony_ci  kResistStopPropagation,
271cb0ef41Sopenharmony_ci  kWeakHandler,
281cb0ef41Sopenharmony_ci} = require('internal/event_target');
291cb0ef41Sopenharmony_ciconst {
301cb0ef41Sopenharmony_ci  createDeferredPromise,
311cb0ef41Sopenharmony_ci  customInspectSymbol,
321cb0ef41Sopenharmony_ci  kEmptyObject,
331cb0ef41Sopenharmony_ci  kEnumerableProperty,
341cb0ef41Sopenharmony_ci} = require('internal/util');
351cb0ef41Sopenharmony_ciconst { inspect } = require('internal/util/inspect');
361cb0ef41Sopenharmony_ciconst {
371cb0ef41Sopenharmony_ci  codes: {
381cb0ef41Sopenharmony_ci    ERR_ILLEGAL_CONSTRUCTOR,
391cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
401cb0ef41Sopenharmony_ci    ERR_INVALID_THIS,
411cb0ef41Sopenharmony_ci  },
421cb0ef41Sopenharmony_ci} = require('internal/errors');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciconst {
451cb0ef41Sopenharmony_ci  validateAbortSignal,
461cb0ef41Sopenharmony_ci  validateAbortSignalArray,
471cb0ef41Sopenharmony_ci  validateObject,
481cb0ef41Sopenharmony_ci  validateUint32,
491cb0ef41Sopenharmony_ci} = require('internal/validators');
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciconst {
521cb0ef41Sopenharmony_ci  DOMException,
531cb0ef41Sopenharmony_ci} = internalBinding('messaging');
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ciconst {
561cb0ef41Sopenharmony_ci  clearTimeout,
571cb0ef41Sopenharmony_ci  setTimeout,
581cb0ef41Sopenharmony_ci} = require('timers');
591cb0ef41Sopenharmony_ciconst assert = require('internal/assert');
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciconst {
621cb0ef41Sopenharmony_ci  messaging_deserialize_symbol: kDeserialize,
631cb0ef41Sopenharmony_ci  messaging_transfer_symbol: kTransfer,
641cb0ef41Sopenharmony_ci  messaging_transfer_list_symbol: kTransferList,
651cb0ef41Sopenharmony_ci} = internalBinding('symbols');
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_cilet _MessageChannel;
681cb0ef41Sopenharmony_cilet makeTransferable;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci// Loading the MessageChannel and makeTransferable have to be done lazily
711cb0ef41Sopenharmony_ci// because otherwise we'll end up with a require cycle that ends up with
721cb0ef41Sopenharmony_ci// an incomplete initialization of abort_controller.
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cifunction lazyMessageChannel() {
751cb0ef41Sopenharmony_ci  _MessageChannel ??= require('internal/worker/io').MessageChannel;
761cb0ef41Sopenharmony_ci  return new _MessageChannel();
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_cifunction lazyMakeTransferable(obj) {
801cb0ef41Sopenharmony_ci  makeTransferable ??=
811cb0ef41Sopenharmony_ci    require('internal/worker/js_transferable').makeTransferable;
821cb0ef41Sopenharmony_ci  return makeTransferable(obj);
831cb0ef41Sopenharmony_ci}
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ciconst clearTimeoutRegistry = new SafeFinalizationRegistry(clearTimeout);
861cb0ef41Sopenharmony_ciconst gcPersistentSignals = new SafeSet();
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ciconst kAborted = Symbol('kAborted');
891cb0ef41Sopenharmony_ciconst kReason = Symbol('kReason');
901cb0ef41Sopenharmony_ciconst kCloneData = Symbol('kCloneData');
911cb0ef41Sopenharmony_ciconst kTimeout = Symbol('kTimeout');
921cb0ef41Sopenharmony_ciconst kMakeTransferable = Symbol('kMakeTransferable');
931cb0ef41Sopenharmony_ciconst kComposite = Symbol('kComposite');
941cb0ef41Sopenharmony_ciconst kSourceSignals = Symbol('kSourceSignals');
951cb0ef41Sopenharmony_ciconst kDependantSignals = Symbol('kDependantSignals');
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_cifunction customInspect(self, obj, depth, options) {
981cb0ef41Sopenharmony_ci  if (depth < 0)
991cb0ef41Sopenharmony_ci    return self;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  const opts = ObjectAssign({}, options, {
1021cb0ef41Sopenharmony_ci    depth: options.depth === null ? null : options.depth - 1,
1031cb0ef41Sopenharmony_ci  });
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  return `${self.constructor.name} ${inspect(obj, opts)}`;
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_cifunction validateThisAbortSignal(obj) {
1091cb0ef41Sopenharmony_ci  if (obj?.[kAborted] === undefined)
1101cb0ef41Sopenharmony_ci    throw new ERR_INVALID_THIS('AbortSignal');
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci// Because the AbortSignal timeout cannot be canceled, we don't want the
1141cb0ef41Sopenharmony_ci// presence of the timer alone to keep the AbortSignal from being garbage
1151cb0ef41Sopenharmony_ci// collected if it otherwise no longer accessible. We also don't want the
1161cb0ef41Sopenharmony_ci// timer to keep the Node.js process open on it's own. Therefore, we wrap
1171cb0ef41Sopenharmony_ci// the AbortSignal in a WeakRef and have the setTimeout callback close
1181cb0ef41Sopenharmony_ci// over the WeakRef rather than directly over the AbortSignal, and we unref
1191cb0ef41Sopenharmony_ci// the created timer object. Separately, we add the signal to a
1201cb0ef41Sopenharmony_ci// FinalizerRegistry that will clear the timeout when the signal is gc'd.
1211cb0ef41Sopenharmony_cifunction setWeakAbortSignalTimeout(weakRef, delay) {
1221cb0ef41Sopenharmony_ci  const timeout = setTimeout(() => {
1231cb0ef41Sopenharmony_ci    const signal = weakRef.deref();
1241cb0ef41Sopenharmony_ci    if (signal !== undefined) {
1251cb0ef41Sopenharmony_ci      gcPersistentSignals.delete(signal);
1261cb0ef41Sopenharmony_ci      abortSignal(
1271cb0ef41Sopenharmony_ci        signal,
1281cb0ef41Sopenharmony_ci        new DOMException(
1291cb0ef41Sopenharmony_ci          'The operation was aborted due to timeout',
1301cb0ef41Sopenharmony_ci          'TimeoutError'));
1311cb0ef41Sopenharmony_ci    }
1321cb0ef41Sopenharmony_ci  }, delay);
1331cb0ef41Sopenharmony_ci  timeout.unref();
1341cb0ef41Sopenharmony_ci  return timeout;
1351cb0ef41Sopenharmony_ci}
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ciclass AbortSignal extends EventTarget {
1381cb0ef41Sopenharmony_ci  constructor() {
1391cb0ef41Sopenharmony_ci    throw new ERR_ILLEGAL_CONSTRUCTOR();
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  /**
1431cb0ef41Sopenharmony_ci   * @type {boolean}
1441cb0ef41Sopenharmony_ci   */
1451cb0ef41Sopenharmony_ci  get aborted() {
1461cb0ef41Sopenharmony_ci    validateThisAbortSignal(this);
1471cb0ef41Sopenharmony_ci    return !!this[kAborted];
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  /**
1511cb0ef41Sopenharmony_ci   * @type {any}
1521cb0ef41Sopenharmony_ci   */
1531cb0ef41Sopenharmony_ci  get reason() {
1541cb0ef41Sopenharmony_ci    validateThisAbortSignal(this);
1551cb0ef41Sopenharmony_ci    return this[kReason];
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  throwIfAborted() {
1591cb0ef41Sopenharmony_ci    validateThisAbortSignal(this);
1601cb0ef41Sopenharmony_ci    if (this[kAborted]) {
1611cb0ef41Sopenharmony_ci      throw this[kReason];
1621cb0ef41Sopenharmony_ci    }
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  [customInspectSymbol](depth, options) {
1661cb0ef41Sopenharmony_ci    return customInspect(this, {
1671cb0ef41Sopenharmony_ci      aborted: this.aborted,
1681cb0ef41Sopenharmony_ci    }, depth, options);
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  /**
1721cb0ef41Sopenharmony_ci   * @param {any} [reason]
1731cb0ef41Sopenharmony_ci   * @returns {AbortSignal}
1741cb0ef41Sopenharmony_ci   */
1751cb0ef41Sopenharmony_ci  static abort(
1761cb0ef41Sopenharmony_ci    reason = new DOMException('This operation was aborted', 'AbortError')) {
1771cb0ef41Sopenharmony_ci    return createAbortSignal({ aborted: true, reason });
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  /**
1811cb0ef41Sopenharmony_ci   * @param {number} delay
1821cb0ef41Sopenharmony_ci   * @returns {AbortSignal}
1831cb0ef41Sopenharmony_ci   */
1841cb0ef41Sopenharmony_ci  static timeout(delay) {
1851cb0ef41Sopenharmony_ci    validateUint32(delay, 'delay', false);
1861cb0ef41Sopenharmony_ci    const signal = createAbortSignal();
1871cb0ef41Sopenharmony_ci    signal[kTimeout] = true;
1881cb0ef41Sopenharmony_ci    clearTimeoutRegistry.register(
1891cb0ef41Sopenharmony_ci      signal,
1901cb0ef41Sopenharmony_ci      setWeakAbortSignalTimeout(new WeakRef(signal), delay));
1911cb0ef41Sopenharmony_ci    return signal;
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  /**
1951cb0ef41Sopenharmony_ci   * @param {AbortSignal[]} signals
1961cb0ef41Sopenharmony_ci   * @returns {AbortSignal}
1971cb0ef41Sopenharmony_ci   */
1981cb0ef41Sopenharmony_ci  static any(signals) {
1991cb0ef41Sopenharmony_ci    validateAbortSignalArray(signals, 'signals');
2001cb0ef41Sopenharmony_ci    const resultSignal = createAbortSignal({ composite: true });
2011cb0ef41Sopenharmony_ci    if (!signals.length) {
2021cb0ef41Sopenharmony_ci      return resultSignal;
2031cb0ef41Sopenharmony_ci    }
2041cb0ef41Sopenharmony_ci    const resultSignalWeakRef = new WeakRef(resultSignal);
2051cb0ef41Sopenharmony_ci    resultSignal[kSourceSignals] = new SafeSet();
2061cb0ef41Sopenharmony_ci    for (let i = 0; i < signals.length; i++) {
2071cb0ef41Sopenharmony_ci      const signal = signals[i];
2081cb0ef41Sopenharmony_ci      if (signal.aborted) {
2091cb0ef41Sopenharmony_ci        abortSignal(resultSignal, signal.reason);
2101cb0ef41Sopenharmony_ci        return resultSignal;
2111cb0ef41Sopenharmony_ci      }
2121cb0ef41Sopenharmony_ci      signal[kDependantSignals] ??= new SafeSet();
2131cb0ef41Sopenharmony_ci      if (!signal[kComposite]) {
2141cb0ef41Sopenharmony_ci        resultSignal[kSourceSignals].add(new WeakRef(signal));
2151cb0ef41Sopenharmony_ci        signal[kDependantSignals].add(resultSignalWeakRef);
2161cb0ef41Sopenharmony_ci      } else if (!signal[kSourceSignals]) {
2171cb0ef41Sopenharmony_ci        continue;
2181cb0ef41Sopenharmony_ci      } else {
2191cb0ef41Sopenharmony_ci        for (const sourceSignal of signal[kSourceSignals]) {
2201cb0ef41Sopenharmony_ci          const sourceSignalRef = sourceSignal.deref();
2211cb0ef41Sopenharmony_ci          if (!sourceSignalRef) {
2221cb0ef41Sopenharmony_ci            continue;
2231cb0ef41Sopenharmony_ci          }
2241cb0ef41Sopenharmony_ci          assert(!sourceSignalRef.aborted);
2251cb0ef41Sopenharmony_ci          assert(!sourceSignalRef[kComposite]);
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci          if (resultSignal[kSourceSignals].has(sourceSignal)) {
2281cb0ef41Sopenharmony_ci            continue;
2291cb0ef41Sopenharmony_ci          }
2301cb0ef41Sopenharmony_ci          resultSignal[kSourceSignals].add(sourceSignal);
2311cb0ef41Sopenharmony_ci          sourceSignalRef[kDependantSignals].add(resultSignalWeakRef);
2321cb0ef41Sopenharmony_ci        }
2331cb0ef41Sopenharmony_ci      }
2341cb0ef41Sopenharmony_ci    }
2351cb0ef41Sopenharmony_ci    return resultSignal;
2361cb0ef41Sopenharmony_ci  }
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  [kNewListener](size, type, listener, once, capture, passive, weak) {
2391cb0ef41Sopenharmony_ci    super[kNewListener](size, type, listener, once, capture, passive, weak);
2401cb0ef41Sopenharmony_ci    const isTimeoutOrNonEmptyCompositeSignal = this[kTimeout] || (this[kComposite] && this[kSourceSignals]?.size);
2411cb0ef41Sopenharmony_ci    if (isTimeoutOrNonEmptyCompositeSignal &&
2421cb0ef41Sopenharmony_ci        type === 'abort' &&
2431cb0ef41Sopenharmony_ci        !this.aborted &&
2441cb0ef41Sopenharmony_ci        !weak &&
2451cb0ef41Sopenharmony_ci        size === 1) {
2461cb0ef41Sopenharmony_ci      // If this is a timeout signal, or a non-empty composite signal, and we're adding a non-weak abort
2471cb0ef41Sopenharmony_ci      // listener, then we don't want it to be gc'd while the listener
2481cb0ef41Sopenharmony_ci      // is attached and the timer still hasn't fired. So, we retain a
2491cb0ef41Sopenharmony_ci      // strong ref that is held for as long as the listener is registered.
2501cb0ef41Sopenharmony_ci      gcPersistentSignals.add(this);
2511cb0ef41Sopenharmony_ci    }
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  [kRemoveListener](size, type, listener, capture) {
2551cb0ef41Sopenharmony_ci    super[kRemoveListener](size, type, listener, capture);
2561cb0ef41Sopenharmony_ci    const isTimeoutOrNonEmptyCompositeSignal = this[kTimeout] || (this[kComposite] && this[kSourceSignals]?.size);
2571cb0ef41Sopenharmony_ci    if (isTimeoutOrNonEmptyCompositeSignal && type === 'abort' && size === 0) {
2581cb0ef41Sopenharmony_ci      gcPersistentSignals.delete(this);
2591cb0ef41Sopenharmony_ci    }
2601cb0ef41Sopenharmony_ci  }
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  [kTransfer]() {
2631cb0ef41Sopenharmony_ci    validateThisAbortSignal(this);
2641cb0ef41Sopenharmony_ci    const aborted = this.aborted;
2651cb0ef41Sopenharmony_ci    if (aborted) {
2661cb0ef41Sopenharmony_ci      const reason = this.reason;
2671cb0ef41Sopenharmony_ci      return {
2681cb0ef41Sopenharmony_ci        data: { aborted, reason },
2691cb0ef41Sopenharmony_ci        deserializeInfo: 'internal/abort_controller:ClonedAbortSignal',
2701cb0ef41Sopenharmony_ci      };
2711cb0ef41Sopenharmony_ci    }
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci    const { port1, port2 } = this[kCloneData];
2741cb0ef41Sopenharmony_ci    this[kCloneData] = undefined;
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci    this.addEventListener('abort', () => {
2771cb0ef41Sopenharmony_ci      port1.postMessage(this.reason);
2781cb0ef41Sopenharmony_ci      port1.close();
2791cb0ef41Sopenharmony_ci    }, { once: true });
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci    return {
2821cb0ef41Sopenharmony_ci      data: { port: port2 },
2831cb0ef41Sopenharmony_ci      deserializeInfo: 'internal/abort_controller:ClonedAbortSignal',
2841cb0ef41Sopenharmony_ci    };
2851cb0ef41Sopenharmony_ci  }
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  [kTransferList]() {
2881cb0ef41Sopenharmony_ci    if (!this.aborted) {
2891cb0ef41Sopenharmony_ci      const { port1, port2 } = lazyMessageChannel();
2901cb0ef41Sopenharmony_ci      port1.unref();
2911cb0ef41Sopenharmony_ci      port2.unref();
2921cb0ef41Sopenharmony_ci      this[kCloneData] = {
2931cb0ef41Sopenharmony_ci        port1,
2941cb0ef41Sopenharmony_ci        port2,
2951cb0ef41Sopenharmony_ci      };
2961cb0ef41Sopenharmony_ci      return [port2];
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci    return [];
2991cb0ef41Sopenharmony_ci  }
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  [kDeserialize]({ aborted, reason, port }) {
3021cb0ef41Sopenharmony_ci    if (aborted) {
3031cb0ef41Sopenharmony_ci      this[kAborted] = aborted;
3041cb0ef41Sopenharmony_ci      this[kReason] = reason;
3051cb0ef41Sopenharmony_ci      return;
3061cb0ef41Sopenharmony_ci    }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci    port.onmessage = ({ data }) => {
3091cb0ef41Sopenharmony_ci      abortSignal(this, data);
3101cb0ef41Sopenharmony_ci      port.close();
3111cb0ef41Sopenharmony_ci      port.onmessage = undefined;
3121cb0ef41Sopenharmony_ci    };
3131cb0ef41Sopenharmony_ci    // The receiving port, by itself, should never keep the event loop open.
3141cb0ef41Sopenharmony_ci    // The unref() has to be called *after* setting the onmessage handler.
3151cb0ef41Sopenharmony_ci    port.unref();
3161cb0ef41Sopenharmony_ci  }
3171cb0ef41Sopenharmony_ci}
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_cifunction ClonedAbortSignal() {
3201cb0ef41Sopenharmony_ci  return createAbortSignal({ transferable: true });
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ciClonedAbortSignal.prototype[kDeserialize] = () => { };
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ciObjectDefineProperties(AbortSignal.prototype, {
3251cb0ef41Sopenharmony_ci  aborted: kEnumerableProperty,
3261cb0ef41Sopenharmony_ci});
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ciObjectDefineProperty(AbortSignal.prototype, SymbolToStringTag, {
3291cb0ef41Sopenharmony_ci  __proto__: null,
3301cb0ef41Sopenharmony_ci  writable: false,
3311cb0ef41Sopenharmony_ci  enumerable: false,
3321cb0ef41Sopenharmony_ci  configurable: true,
3331cb0ef41Sopenharmony_ci  value: 'AbortSignal',
3341cb0ef41Sopenharmony_ci});
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_cidefineEventHandler(AbortSignal.prototype, 'abort');
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci/**
3391cb0ef41Sopenharmony_ci * @param {{
3401cb0ef41Sopenharmony_ci *   aborted? : boolean,
3411cb0ef41Sopenharmony_ci *   reason? : any,
3421cb0ef41Sopenharmony_ci *   transferable? : boolean,
3431cb0ef41Sopenharmony_ci *   composite? : boolean,
3441cb0ef41Sopenharmony_ci * }} [init]
3451cb0ef41Sopenharmony_ci * @returns {AbortSignal}
3461cb0ef41Sopenharmony_ci */
3471cb0ef41Sopenharmony_cifunction createAbortSignal(init = kEmptyObject) {
3481cb0ef41Sopenharmony_ci  const {
3491cb0ef41Sopenharmony_ci    aborted = false,
3501cb0ef41Sopenharmony_ci    reason = undefined,
3511cb0ef41Sopenharmony_ci    transferable = false,
3521cb0ef41Sopenharmony_ci    composite = false,
3531cb0ef41Sopenharmony_ci  } = init;
3541cb0ef41Sopenharmony_ci  const signal = new EventTarget();
3551cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf(signal, AbortSignal.prototype);
3561cb0ef41Sopenharmony_ci  signal[kAborted] = aborted;
3571cb0ef41Sopenharmony_ci  signal[kReason] = reason;
3581cb0ef41Sopenharmony_ci  signal[kComposite] = composite;
3591cb0ef41Sopenharmony_ci  return transferable ? lazyMakeTransferable(signal) : signal;
3601cb0ef41Sopenharmony_ci}
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_cifunction abortSignal(signal, reason) {
3631cb0ef41Sopenharmony_ci  if (signal[kAborted]) return;
3641cb0ef41Sopenharmony_ci  signal[kAborted] = true;
3651cb0ef41Sopenharmony_ci  signal[kReason] = reason;
3661cb0ef41Sopenharmony_ci  const event = new Event('abort', {
3671cb0ef41Sopenharmony_ci    [kTrustEvent]: true,
3681cb0ef41Sopenharmony_ci  });
3691cb0ef41Sopenharmony_ci  signal.dispatchEvent(event);
3701cb0ef41Sopenharmony_ci  signal[kDependantSignals]?.forEach((s) => {
3711cb0ef41Sopenharmony_ci    const signalRef = s.deref();
3721cb0ef41Sopenharmony_ci    if (signalRef) abortSignal(signalRef, reason);
3731cb0ef41Sopenharmony_ci  });
3741cb0ef41Sopenharmony_ci}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci// TODO(joyeecheung): use private fields and we'll get invalid access
3771cb0ef41Sopenharmony_ci// validation from V8 instead of throwing ERR_INVALID_THIS ourselves.
3781cb0ef41Sopenharmony_ciconst kSignal = Symbol('signal');
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_cifunction validateAbortController(obj) {
3811cb0ef41Sopenharmony_ci  if (obj?.[kSignal] === undefined)
3821cb0ef41Sopenharmony_ci    throw new ERR_INVALID_THIS('AbortController');
3831cb0ef41Sopenharmony_ci}
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ciclass AbortController {
3861cb0ef41Sopenharmony_ci  constructor() {
3871cb0ef41Sopenharmony_ci    this[kSignal] = createAbortSignal();
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  /**
3911cb0ef41Sopenharmony_ci   * @type {AbortSignal}
3921cb0ef41Sopenharmony_ci   */
3931cb0ef41Sopenharmony_ci  get signal() {
3941cb0ef41Sopenharmony_ci    validateAbortController(this);
3951cb0ef41Sopenharmony_ci    return this[kSignal];
3961cb0ef41Sopenharmony_ci  }
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  /**
3991cb0ef41Sopenharmony_ci   * @param {any} [reason]
4001cb0ef41Sopenharmony_ci   */
4011cb0ef41Sopenharmony_ci  abort(reason = new DOMException('This operation was aborted', 'AbortError')) {
4021cb0ef41Sopenharmony_ci    validateAbortController(this);
4031cb0ef41Sopenharmony_ci    abortSignal(this[kSignal], reason);
4041cb0ef41Sopenharmony_ci  }
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  [customInspectSymbol](depth, options) {
4071cb0ef41Sopenharmony_ci    return customInspect(this, {
4081cb0ef41Sopenharmony_ci      signal: this.signal,
4091cb0ef41Sopenharmony_ci    }, depth, options);
4101cb0ef41Sopenharmony_ci  }
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  static [kMakeTransferable]() {
4131cb0ef41Sopenharmony_ci    const controller = new AbortController();
4141cb0ef41Sopenharmony_ci    controller[kSignal] = transferableAbortSignal(controller[kSignal]);
4151cb0ef41Sopenharmony_ci    return controller;
4161cb0ef41Sopenharmony_ci  }
4171cb0ef41Sopenharmony_ci}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci/**
4201cb0ef41Sopenharmony_ci * Enables the AbortSignal to be transferable using structuredClone/postMessage.
4211cb0ef41Sopenharmony_ci * @param {AbortSignal} signal
4221cb0ef41Sopenharmony_ci * @returns {AbortSignal}
4231cb0ef41Sopenharmony_ci */
4241cb0ef41Sopenharmony_cifunction transferableAbortSignal(signal) {
4251cb0ef41Sopenharmony_ci  if (signal?.[kAborted] === undefined)
4261cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal);
4271cb0ef41Sopenharmony_ci  return lazyMakeTransferable(signal);
4281cb0ef41Sopenharmony_ci}
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci/**
4311cb0ef41Sopenharmony_ci * Creates an AbortController with a transferable AbortSignal
4321cb0ef41Sopenharmony_ci */
4331cb0ef41Sopenharmony_cifunction transferableAbortController() {
4341cb0ef41Sopenharmony_ci  return AbortController[kMakeTransferable]();
4351cb0ef41Sopenharmony_ci}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci/**
4381cb0ef41Sopenharmony_ci * @param {AbortSignal} signal
4391cb0ef41Sopenharmony_ci * @param {any} resource
4401cb0ef41Sopenharmony_ci * @returns {Promise<void>}
4411cb0ef41Sopenharmony_ci */
4421cb0ef41Sopenharmony_ciasync function aborted(signal, resource) {
4431cb0ef41Sopenharmony_ci  if (signal === undefined) {
4441cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal);
4451cb0ef41Sopenharmony_ci  }
4461cb0ef41Sopenharmony_ci  validateAbortSignal(signal, 'signal');
4471cb0ef41Sopenharmony_ci  validateObject(resource, 'resource', { nullable: false, allowFunction: true, allowArray: true });
4481cb0ef41Sopenharmony_ci  if (signal.aborted)
4491cb0ef41Sopenharmony_ci    return PromiseResolve();
4501cb0ef41Sopenharmony_ci  const abortPromise = createDeferredPromise();
4511cb0ef41Sopenharmony_ci  const opts = { __proto__: null, [kWeakHandler]: resource, once: true, [kResistStopPropagation]: true };
4521cb0ef41Sopenharmony_ci  signal.addEventListener('abort', abortPromise.resolve, opts);
4531cb0ef41Sopenharmony_ci  return abortPromise.promise;
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ciObjectDefineProperties(AbortController.prototype, {
4571cb0ef41Sopenharmony_ci  signal: kEnumerableProperty,
4581cb0ef41Sopenharmony_ci  abort: kEnumerableProperty,
4591cb0ef41Sopenharmony_ci});
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ciObjectDefineProperty(AbortController.prototype, SymbolToStringTag, {
4621cb0ef41Sopenharmony_ci  __proto__: null,
4631cb0ef41Sopenharmony_ci  writable: false,
4641cb0ef41Sopenharmony_ci  enumerable: false,
4651cb0ef41Sopenharmony_ci  configurable: true,
4661cb0ef41Sopenharmony_ci  value: 'AbortController',
4671cb0ef41Sopenharmony_ci});
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_cimodule.exports = {
4701cb0ef41Sopenharmony_ci  AbortController,
4711cb0ef41Sopenharmony_ci  AbortSignal,
4721cb0ef41Sopenharmony_ci  ClonedAbortSignal,
4731cb0ef41Sopenharmony_ci  aborted,
4741cb0ef41Sopenharmony_ci  transferableAbortSignal,
4751cb0ef41Sopenharmony_ci  transferableAbortController,
4761cb0ef41Sopenharmony_ci};
477