lib: clean up persisted signals when they are settled · nodejs/node@a3c8739
@@ -97,8 +97,21 @@ const dependantSignalsCleanupRegistry = new SafeFinalizationRegistry((signalWeak
9797}
9898});
9999});
100+100101const gcPersistentSignals = new SafeSet();
101102103+const sourceSignalsCleanupRegistry = new SafeFinalizationRegistry(({ sourceSignalRef, composedSignalRef }) => {
104+const composedSignal = composedSignalRef.deref();
105+if (composedSignal !== undefined) {
106+composedSignal[kSourceSignals].delete(sourceSignalRef);
107+108+if (composedSignal[kSourceSignals].size === 0) {
109+// This signal will no longer abort. There's no need to keep it in the gcPersistentSignals set.
110+gcPersistentSignals.delete(composedSignal);
111+}
112+}
113+});
114+102115const kAborted = Symbol('kAborted');
103116const kReason = Symbol('kReason');
104117const kCloneData = Symbol('kCloneData');
@@ -261,6 +274,10 @@ class AbortSignal extends EventTarget {
261274resultSignal[kSourceSignals].add(signalWeakRef);
262275signal[kDependantSignals].add(resultSignalWeakRef);
263276dependantSignalsCleanupRegistry.register(resultSignal, signalWeakRef);
277+sourceSignalsCleanupRegistry.register(signal, {
278+sourceSignalRef: signalWeakRef,
279+composedSignalRef: resultSignalWeakRef,
280+});
264281} else if (!signal[kSourceSignals]) {
265282continue;
266283} else {
@@ -278,6 +295,10 @@ class AbortSignal extends EventTarget {
278295resultSignal[kSourceSignals].add(sourceSignalWeakRef);
279296sourceSignal[kDependantSignals].add(resultSignalWeakRef);
280297dependantSignalsCleanupRegistry.register(resultSignal, sourceSignalWeakRef);
298+sourceSignalsCleanupRegistry.register(signal, {
299+sourceSignalRef: sourceSignalWeakRef,
300+composedSignalRef: resultSignalWeakRef,
301+});
281302}
282303}
283304}
@@ -434,6 +455,7 @@ class AbortController {
434455 */
435456get signal() {
436457this.#signal ??= new AbortSignal(kDontThrowSymbol);
458+437459return this.#signal;
438460}
439461