diff --git a/lib/internal/abort_controller.js b/lib/internal/abort_controller.js index 55be0b6f3669..d57beba2e3ad 100644 --- a/lib/internal/abort_controller.js +++ b/lib/internal/abort_controller.js @@ -336,6 +336,12 @@ class AbortSignal extends EventTarget { for (let i = 0; i < signalsArray.length; i++) { const signal = signalsArray[i]; + refreshCompositeSignal(signal); + if (signal[kAborted]) { + abortSignal(resultSignal, signal[kReason]); + return resultSignal; + } + // Check if this is a timeout signal if (signal[kTimeout]) { hasTimeoutSignals = true; @@ -345,12 +351,6 @@ class AbortSignal extends EventTarget { gcPersistentSignals.add(signal); } - refreshCompositeSignal(signal); - if (signal[kAborted]) { - abortSignal(resultSignal, signal[kReason]); - return resultSignal; - } - if (!signal[kComposite]) { const signalWeakRef = new SafeWeakRef(signal); resultSignal[kSourceSignals].add(signalWeakRef); diff --git a/test/parallel/test-abort-controller-any-timeout.js b/test/parallel/test-abort-controller-any-timeout.js index 675be3af703c..51acdbb16d21 100644 --- a/test/parallel/test-abort-controller-any-timeout.js +++ b/test/parallel/test-abort-controller-any-timeout.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { gcUntil } = require('../common/gc'); const assert = require('assert'); const { once } = require('node:events'); const { describe, it } = require('node:test'); @@ -39,4 +40,15 @@ describe('AbortSignal.any() with timeout signals', () => { clearTimeout(timeout); } }); + + it('should not retain a timeout signal that has already fired', async () => { + let signal = AbortSignal.timeout(1); + const ref = new WeakRef(signal); + await once(signal, 'abort'); + + AbortSignal.any([signal]); + signal = null; + + await gcUntil('fired timeout signal is collected', () => ref.deref() === undefined); + }); });