@@ -32,6 +32,7 @@ import type {
3232 GraphQLObjectType ,
3333 GraphQLOutputType ,
3434 GraphQLResolveInfo ,
35+ GraphQLResolveInfoHelpers ,
3536 GraphQLTypeResolver ,
3637} from '../type/definition.js' ;
3738import {
@@ -231,6 +232,11 @@ export class Executor<
231232 abortResultPromise : ( ( reason ?: unknown ) => void ) | undefined ;
232233 resolverAbortController : AbortController | undefined ;
233234 getAbortSignal : ( ) => AbortSignal | undefined ;
235+ getAsyncHelpers : ( ) => GraphQLResolveInfoHelpers ;
236+ promiseAll : < T > (
237+ values : ReadonlyArray < PromiseOrValue < T > > ,
238+ ) => Promise < Array < T > > ;
239+ trackPromise : ( promise : Promise < unknown > ) => void ;
234240
235241 constructor (
236242 validatedExecutionArgs : ValidatedExecutionArgs ,
@@ -249,8 +255,12 @@ export class Executor<
249255 } else {
250256 this . sharedExecutionContext = sharedExecutionContext ;
251257 }
252- const { getAbortSignal } = this . sharedExecutionContext ;
258+ const { getAbortSignal, getAsyncHelpers, promiseAll, trackPromise } =
259+ this . sharedExecutionContext ;
253260 this . getAbortSignal = getAbortSignal ;
261+ this . getAsyncHelpers = getAsyncHelpers ;
262+ this . promiseAll = promiseAll ;
263+ this . trackPromise = trackPromise ;
254264 }
255265
256266 executeQueryOrMutationOrSubscriptionEvent ( ) : PromiseOrValue <
@@ -261,10 +271,7 @@ export class Executor<
261271 if ( externalAbortSignal ) {
262272 externalAbortSignal . throwIfAborted ( ) ;
263273 const onExternalAbort = ( ) => {
264- const aborted = this . abort ( externalAbortSignal . reason ) ;
265- if ( isPromise ( aborted ) ) {
266- aborted . catch ( ( ) => undefined ) ;
267- }
274+ this . abort ( externalAbortSignal . reason ) ;
268275 } ;
269276 removeExternalAbortListener = ( ) =>
270277 externalAbortSignal . removeEventListener ( 'abort' , onExternalAbort ) ;
@@ -324,6 +331,7 @@ export class Executor<
324331 return this . buildResponse ( null ) ;
325332 } ,
326333 ) ;
334+ this . sharedExecutionContext . asyncWorkTracker . add ( promise ) ;
327335 const { promise : cancellablePromise , abort : abortResultPromise } =
328336 withCancellation ( promise ) ;
329337 this . abortResultPromise = abortResultPromise ;
@@ -347,7 +355,7 @@ export class Executor<
347355 }
348356 }
349357
350- abort ( reason ?: unknown ) : PromiseOrValue < void > {
358+ abort ( reason ?: unknown ) : void {
351359 if ( this . aborted ) {
352360 return ;
353361 }
@@ -506,8 +514,9 @@ export class Executor<
506514 }
507515 } catch ( error ) {
508516 if ( containsPromise ) {
509- // Ensure that any promises returned by other fields are handled, as they may also reject.
510- promiseForObject ( results ) . catch ( ( ) => undefined ) ;
517+ this . sharedExecutionContext . asyncWorkTracker . addValues (
518+ Object . values ( results ) ,
519+ ) ;
511520 }
512521 throw error ;
513522 }
@@ -520,7 +529,7 @@ export class Executor<
520529 // Otherwise, results is a map from field name to the result of resolving that
521530 // field, which is possibly a promise. Return a promise that will return this
522531 // same map, but with any promises replaced with the values they resolved to.
523- return promiseForObject ( results ) ;
532+ return promiseForObject ( results , this . promiseAll ) ;
524533 }
525534
526535 /**
@@ -557,6 +566,7 @@ export class Executor<
557566 parentType ,
558567 path ,
559568 this . getAbortSignal ,
569+ this . getAsyncHelpers ,
560570 ) ;
561571
562572 // Get the resolve function, regardless of if its result is normal or abrupt (error).
@@ -853,24 +863,26 @@ export class Executor<
853863 index ++ ;
854864 }
855865 } catch ( error ) {
856- // eslint-disable-next-line @typescript-eslint/no-floating-promises
857- returnIteratorCatchingErrors ( asyncIterator ) ;
866+ this . trackPromise ( returnIteratorCatchingErrors ( asyncIterator ) ) ;
858867 if ( containsPromise ) {
859- Promise . all ( completedResults ) . catch ( ( ) => undefined ) ;
868+ this . sharedExecutionContext . asyncWorkTracker . addValues (
869+ completedResults ,
870+ ) ;
860871 }
861872 throw error ;
862873 }
863874
864875 // Throwing on completion outside of the loop may allow engines to better optimize
865876 if ( this . aborted ) {
866877 if ( ! iteration ?. done ) {
867- // eslint-disable-next-line @typescript-eslint/no-floating-promises
868- returnIteratorCatchingErrors ( asyncIterator ) ;
878+ this . trackPromise ( returnIteratorCatchingErrors ( asyncIterator ) ) ;
869879 }
870880 throw new Error ( 'Aborted!' ) ;
871881 }
872882
873- return containsPromise ? Promise . all ( completedResults ) : completedResults ;
883+ return containsPromise
884+ ? this . promiseAll ( completedResults )
885+ : completedResults ;
874886 }
875887
876888 /* c8 ignore next 12 */
@@ -991,15 +1003,17 @@ export class Executor<
9911003 index ++ ;
9921004 }
9931005 } catch ( error ) {
994- const maybePromises = containsPromise ? completedResults : [ ] ;
995- maybePromises . push ( ...collectIteratorPromises ( iterator ) ) ;
996- if ( maybePromises . length ) {
997- Promise . all ( maybePromises ) . catch ( ( ) => undefined ) ;
1006+ const asyncWorkTracker = this . sharedExecutionContext . asyncWorkTracker ;
1007+ if ( containsPromise ) {
1008+ asyncWorkTracker . addValues ( completedResults ) ;
9981009 }
1010+ asyncWorkTracker . addValues ( collectIteratorPromises ( iterator ) ) ;
9991011 throw error ;
10001012 }
10011013
1002- return containsPromise ? Promise . all ( completedResults ) : completedResults ;
1014+ return containsPromise
1015+ ? this . promiseAll ( completedResults )
1016+ : completedResults ;
10031017 }
10041018
10051019 completeMaybePromisedListItemValue (
0 commit comments