UNPKG

@graphql-hive/signal

Version:
139 lines (134 loc) 4.05 kB
'use strict'; const isNode = !globalThis.Bun && globalThis.process?.release?.name === "node"; const controllerInSignalSy = Symbol("CONTROLLER_IN_SIGNAL"); const signalRegistry = new FinalizationRegistry( (cb) => cb() ); function abortSignalAny(signals) { if (signals.length === 0) { return void 0; } if (signals.length === 1) { return signals[0]; } if (!isNode) { return AbortSignal.any(signals); } for (const signal of signals) { if (signal.aborted) { return signal; } } const ctrl = new AbortController(); const ctrlRef = new WeakRef(ctrl); const eventListenerPairs = []; let retainedSignalsCount = signals.length; for (const signal of signals) { let abort2 = function() { ctrlRef.deref()?.abort(signalRef.deref()?.reason); }; const signalRef = new WeakRef(signal); signal.addEventListener("abort", abort2); eventListenerPairs.push([signalRef, abort2]); signalRegistry.register( signal, () => ( // dispose when all of the signals have been GCed !--retainedSignalsCount && dispose() ), signal ); } function dispose() { for (const [signalRef, abort2] of eventListenerPairs) { const signal = signalRef.deref(); if (signal) { signal.removeEventListener("abort", abort2); signalRegistry.unregister(signal); } const ctrl2 = ctrlRef.deref(); if (ctrl2) { signalRegistry.unregister(ctrl2.signal); delete ctrl2.signal[controllerInSignalSy]; } } } ctrl.signal.addEventListener("abort", dispose); signalRegistry.register(ctrl.signal, dispose, ctrl.signal); ctrl.signal[controllerInSignalSy] = ctrl; return ctrl.signal; } function abortSignalAll(signals) { if (signals.length === 0) { return void 0; } if (signals.length === 1) { return signals[0]; } if (signals.every((signal) => signal.aborted)) { const errors2 = signals.map((signal) => signal.reason).filter( (reason) => reason != null && !reason?.toString?.()?.includes("AbortError") ); if (errors2.length < 2) { return signals[0]; } else { return AbortSignal.abort(new AggregateError(errors2)); } } const ctrl = new AbortController(); const ctrlRef = new WeakRef(ctrl); const eventListenerPairs = []; let retainedSignalsCount = signals.length; let remainingSignalsToAbort = signals.length; const errors = /* @__PURE__ */ new Set(); for (const signal of signals) { let onAbort2 = function() { remainingSignalsToAbort--; const reason = signal.reason; if (reason != null && !reason?.toString().includes("AbortError")) { errors.add(reason); } if (remainingSignalsToAbort === 0) { let error; if (errors.size < 2) { error = errors.values().next().value; } else { error = new AggregateError(errors); } ctrlRef.deref()?.abort(error); } }; const signalRef = new WeakRef(signal); signal.addEventListener("abort", onAbort2); eventListenerPairs.push([signalRef, onAbort2]); signalRegistry.register( signal, () => ( // dispose when all of the signals have been GCed !--retainedSignalsCount && dispose() ), signal ); } function dispose() { for (const [signalRef, abort] of eventListenerPairs) { const signal = signalRef.deref(); if (signal) { signal.removeEventListener("abort", abort); signalRegistry.unregister(signal); } } const ctrl2 = ctrlRef.deref(); if (ctrl2) { ctrl2.signal.removeEventListener("abort", dispose); signalRegistry.unregister(ctrl2.signal); delete ctrl2.signal[controllerInSignalSy]; } } ctrl.signal.addEventListener("abort", dispose); signalRegistry.register(ctrl.signal, dispose, ctrl.signal); ctrl.signal[controllerInSignalSy] = ctrl; return ctrl.signal; } exports.abortSignalAll = abortSignalAll; exports.abortSignalAny = abortSignalAny;