@@ -29,6 +29,9 @@ const { kConstruct } = require('../../core/symbols')
2929const assert = require ( 'node:assert' )
3030const { getMaxListeners, setMaxListeners, defaultMaxListeners } = require ( 'node:events' )
3131
32+ // https://github.com/nodejs/node/commit/d4736060404726a24d4e52647b8c9b88914b8ddf
33+ const isFixedOrderAbortSignalAny = typeof AbortSignal . any === 'function' && util . nodeMajor >= 23
34+
3235const kAbortController = Symbol ( 'abortController' )
3336
3437const requestFinalizer = new FinalizationRegistry ( ( { signal, abort } ) => {
@@ -407,39 +410,44 @@ class Request {
407410 // Realm.
408411 // TODO: could this be simplified with AbortSignal.any
409412 // (https://dom.spec.whatwg.org/#dom-abortsignal-any)
410- const ac = new AbortController ( )
411- this . #signal = ac . signal
412-
413- // 29. If signal is not null, then make this’s signal follow signal.
414- if ( signal != null ) {
415- if ( signal . aborted ) {
416- ac . abort ( signal . reason )
417- } else {
418- // Keep a strong ref to ac while request object
419- // is alive. This is needed to prevent AbortController
420- // from being prematurely garbage collected.
421- // See, https://github.com/nodejs/undici/issues/1926.
422- this [ kAbortController ] = ac
423-
424- const acRef = new WeakRef ( ac )
425- const abort = buildAbort ( acRef )
413+ if ( isFixedOrderAbortSignalAny ) {
414+ // 29. If signal is not null, then make this’s signal follow signal.
415+ this . #signal = AbortSignal . any ( signal != null ? [ signal ] : [ ] )
416+ } else {
417+ const ac = new AbortController ( )
418+ this . #signal = ac . signal
426419
427- // Third-party AbortControllers may not work with these.
428- // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
429- try {
430- // If the max amount of listeners is equal to the default, increase it
431- // This is only available in node >= v19.9.0
432- if ( typeof getMaxListeners === 'function' && getMaxListeners ( signal ) === defaultMaxListeners ) {
433- setMaxListeners ( 1500 , signal )
434- }
435- } catch { }
436-
437- util . addAbortListener ( signal , abort )
438- // The third argument must be a registry key to be unregistered.
439- // Without it, you cannot unregister.
440- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
441- // abort is used as the unregister key. (because it is unique)
442- requestFinalizer . register ( ac , { signal, abort } , abort )
420+ // 29. If signal is not null, then make this’s signal follow signal.
421+ if ( signal != null ) {
422+ if ( signal . aborted ) {
423+ ac . abort ( signal . reason )
424+ } else {
425+ // Keep a strong ref to ac while request object
426+ // is alive. This is needed to prevent AbortController
427+ // from being prematurely garbage collected.
428+ // See, https://github.com/nodejs/undici/issues/1926.
429+ this [ kAbortController ] = ac
430+
431+ const acRef = new WeakRef ( ac )
432+ const abort = buildAbort ( acRef )
433+
434+ // Third-party AbortControllers may not work with these.
435+ // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
436+ try {
437+ // If the max amount of listeners is equal to the default, increase it
438+ // This is only available in node >= v19.9.0
439+ if ( typeof getMaxListeners === 'function' && getMaxListeners ( signal ) === defaultMaxListeners ) {
440+ setMaxListeners ( 1500 , signal )
441+ }
442+ } catch { }
443+
444+ util . addAbortListener ( signal , abort )
445+ // The third argument must be a registry key to be unregistered.
446+ // Without it, you cannot unregister.
447+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
448+ // abort is used as the unregister key. (because it is unique)
449+ requestFinalizer . register ( ac , { signal, abort } , abort )
450+ }
443451 }
444452 }
445453
@@ -771,25 +779,33 @@ class Request {
771779 // 3. Let clonedRequestObject be the result of creating a Request object,
772780 // given clonedRequest, this’s headers’s guard, and this’s relevant Realm.
773781 // 4. Make clonedRequestObject’s signal follow this’s signal.
774- const ac = new AbortController ( )
775- if ( this . signal . aborted ) {
776- ac . abort ( this . signal . reason )
782+ let signal
783+
784+ if ( isFixedOrderAbortSignalAny ) {
785+ signal = AbortSignal . any ( [ this . #signal] )
777786 } else {
778- let list = dependentControllerMap . get ( this . signal )
779- if ( list === undefined ) {
780- list = new Set ( )
781- dependentControllerMap . set ( this . signal , list )
787+ const ac = new AbortController ( )
788+ if ( this . #signal. aborted ) {
789+ ac . abort ( this . #signal. reason )
790+ } else {
791+ let list = dependentControllerMap . get ( this . #signal)
792+ if ( list === undefined ) {
793+ list = new Set ( )
794+ dependentControllerMap . set ( this . #signal, list )
795+ }
796+ const acRef = new WeakRef ( ac )
797+ list . add ( acRef )
798+ util . addAbortListener (
799+ ac . signal ,
800+ buildAbort ( acRef )
801+ )
782802 }
783- const acRef = new WeakRef ( ac )
784- list . add ( acRef )
785- util . addAbortListener (
786- ac . signal ,
787- buildAbort ( acRef )
788- )
803+
804+ signal = ac . signal
789805 }
790806
791807 // 4. Return clonedRequestObject.
792- return fromInnerRequest ( clonedRequest , this . #dispatcher, ac . signal , getHeadersGuard ( this . #headers) )
808+ return fromInnerRequest ( clonedRequest , this . #dispatcher, signal , getHeadersGuard ( this . #headers) )
793809 }
794810
795811 [ nodeUtil . inspect . custom ] ( depth , options ) {
0 commit comments