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