lib: clean up persisted signals when they are settled · nodejs/node@fd55d3c
@@ -96,8 +96,21 @@ const dependantSignalsCleanupRegistry = new SafeFinalizationRegistry((signalWeak
9696}
9797});
9898});
99+99100const gcPersistentSignals = new SafeSet();
100101102+const sourceSignalsCleanupRegistry = new SafeFinalizationRegistry(({ sourceSignalRef, composedSignalRef }) => {
103+const composedSignal = composedSignalRef.deref();
104+if (composedSignal !== undefined) {
105+composedSignal[kSourceSignals].delete(sourceSignalRef);
106+107+if (composedSignal[kSourceSignals].size === 0) {
108+// This signal will no longer abort. There's no need to keep it in the gcPersistentSignals set.
109+gcPersistentSignals.delete(composedSignal);
110+}
111+}
112+});
113+101114const kAborted = Symbol('kAborted');
102115const kReason = Symbol('kReason');
103116const kCloneData = Symbol('kCloneData');
@@ -260,6 +273,10 @@ class AbortSignal extends EventTarget {
260273resultSignal[kSourceSignals].add(signalWeakRef);
261274signal[kDependantSignals].add(resultSignalWeakRef);
262275dependantSignalsCleanupRegistry.register(resultSignal, signalWeakRef);
276+sourceSignalsCleanupRegistry.register(signal, {
277+sourceSignalRef: signalWeakRef,
278+composedSignalRef: resultSignalWeakRef,
279+});
263280} else if (!signal[kSourceSignals]) {
264281continue;
265282} else {
@@ -277,6 +294,10 @@ class AbortSignal extends EventTarget {
277294resultSignal[kSourceSignals].add(sourceSignalWeakRef);
278295sourceSignal[kDependantSignals].add(resultSignalWeakRef);
279296dependantSignalsCleanupRegistry.register(resultSignal, sourceSignalWeakRef);
297+sourceSignalsCleanupRegistry.register(signal, {
298+sourceSignalRef: sourceSignalWeakRef,
299+composedSignalRef: resultSignalWeakRef,
300+});
280301}
281302}
282303}
@@ -436,6 +457,7 @@ class AbortController {
436457 */
437458get signal() {
438459this.#signal ??= new AbortSignal(kDontThrowSymbol);
460+439461return this.#signal;
440462}
441463