Skip to content

Commit 86f7b92

Browse files
committed
lib: settle signals when controller's signal is GCed
1 parent 4f62ab5 commit 86f7b92

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

lib/internal/abort_controller.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,25 @@ const dependantSignalsCleanupRegistry = new SafeFinalizationRegistry((signalWeak
9595
}
9696
});
9797
});
98+
9899
const gcPersistentSignals = new SafeSet();
99100

101+
const finalizer = new SafeFinalizationRegistry(({ sourceSignalRef, composedSignalRef }) => {
102+
// TODO: remove ref from source signal
103+
// TODO: remove composed signal from gcPersistentSignals
104+
const composedSignal = composedSignalRef.deref();
105+
if (composedSignal !== undefined) {
106+
composedSignal[kSourceSignals].delete(sourceSignalRef);
107+
gcPersistentSignals.delete(composedSignal);
108+
}
109+
110+
// TODO: remove ref from dependant signal
111+
const sourceSignal = sourceSignalRef.deref();
112+
if (sourceSignal !== undefined) {
113+
sourceSignal[kDependantSignals].delete(composedSignalRef);
114+
}
115+
});
116+
100117
const kAborted = Symbol('kAborted');
101118
const kReason = Symbol('kReason');
102119
const kCloneData = Symbol('kCloneData');
@@ -258,6 +275,9 @@ class AbortSignal extends EventTarget {
258275
resultSignal[kSourceSignals].add(signalWeakRef);
259276
signal[kDependantSignals].add(resultSignalWeakRef);
260277
dependantSignalsCleanupRegistry.register(resultSignal, signalWeakRef);
278+
// when the source signal - coming from the controller - is gced, we need to remove it from the dependant
279+
// signals of the composite signal
280+
finalizer.register(signal, { sourceSignalRef: signalWeakRef, composedSignalRef: resultSignalWeakRef});
261281
} else if (!signal[kSourceSignals]) {
262282
continue;
263283
} else {
@@ -293,6 +313,7 @@ class AbortSignal extends EventTarget {
293313
// listener, then we don't want it to be gc'd while the listener
294314
// is attached and the timer still hasn't fired. So, we retain a
295315
// strong ref that is held for as long as the listener is registered.
316+
296317
gcPersistentSignals.add(this);
297318
}
298319
}
@@ -434,6 +455,7 @@ class AbortController {
434455
*/
435456
get signal() {
436457
this.#signal ??= new AbortSignal(kDontThrowSymbol);
458+
437459
return this.#signal;
438460
}
439461

0 commit comments

Comments
 (0)