@@ -165,11 +165,13 @@ export interface ExecutionContext {
165
165
validatedExecutionArgs : ValidatedExecutionArgs ;
166
166
errors : Array < GraphQLError > | undefined ;
167
167
promiseCanceller : PromiseCanceller | undefined ;
168
+ completed : boolean ;
168
169
cancellableStreams : Set < CancellableStreamRecord > | undefined ;
169
170
}
170
171
171
172
interface IncrementalContext {
172
173
errors : Array < GraphQLError > | undefined ;
174
+ completed : boolean ;
173
175
deferUsageSet ?: DeferUsageSet | undefined ;
174
176
}
175
177
@@ -319,6 +321,7 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
319
321
promiseCanceller : abortSignal
320
322
? new PromiseCanceller ( abortSignal )
321
323
: undefined ,
324
+ completed : false ,
322
325
cancellableStreams : undefined ,
323
326
} ;
324
327
try {
@@ -359,8 +362,12 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
359
362
360
363
if ( isPromise ( graphqlWrappedResult ) ) {
361
364
return graphqlWrappedResult . then (
362
- ( resolved ) => buildDataResponse ( exeContext , resolved ) ,
365
+ ( resolved ) => {
366
+ exeContext . completed = true ;
367
+ return buildDataResponse ( exeContext , resolved ) ;
368
+ } ,
363
369
( error : unknown ) => {
370
+ exeContext . completed = true ;
364
371
exeContext . promiseCanceller ?. disconnect ( ) ;
365
372
return {
366
373
data : null ,
@@ -369,8 +376,10 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
369
376
} ,
370
377
) ;
371
378
}
379
+ exeContext . completed = true ;
372
380
return buildDataResponse ( exeContext , graphqlWrappedResult ) ;
373
381
} catch ( error ) {
382
+ exeContext . completed = true ;
374
383
// TODO: add test case for synchronous null bubbling to root with cancellation
375
384
/* c8 ignore next */
376
385
exeContext . promiseCanceller ?. disconnect ( ) ;
@@ -1760,6 +1769,10 @@ function completeObjectValue(
1760
1769
incrementalContext : IncrementalContext | undefined ,
1761
1770
deferMap : ReadonlyMap < DeferUsage , DeferredFragmentRecord > | undefined ,
1762
1771
) : PromiseOrValue < GraphQLWrappedResult < ObjMap < unknown > > > {
1772
+ if ( ( incrementalContext ?? exeContext ) . completed ) {
1773
+ throw new Error ( 'Completed, aborting.' ) ;
1774
+ }
1775
+
1763
1776
// If there is an isTypeOf predicate function, call it with the
1764
1777
// current result. If isTypeOf returns false, then raise an error rather
1765
1778
// than continuing execution.
@@ -2324,6 +2337,7 @@ function collectExecutionGroups(
2324
2337
groupedFieldSet ,
2325
2338
{
2326
2339
errors : undefined ,
2340
+ completed : false ,
2327
2341
deferUsageSet,
2328
2342
} ,
2329
2343
deferMap ,
@@ -2383,6 +2397,7 @@ function executeExecutionGroup(
2383
2397
deferMap ,
2384
2398
) ;
2385
2399
} catch ( error ) {
2400
+ incrementalContext . completed = true ;
2386
2401
return {
2387
2402
pendingExecutionGroup,
2388
2403
path : pathToArray ( path ) ,
@@ -2392,21 +2407,27 @@ function executeExecutionGroup(
2392
2407
2393
2408
if ( isPromise ( result ) ) {
2394
2409
return result . then (
2395
- ( resolved ) =>
2396
- buildCompletedExecutionGroup (
2410
+ ( resolved ) => {
2411
+ incrementalContext . completed = true ;
2412
+ return buildCompletedExecutionGroup (
2397
2413
incrementalContext . errors ,
2398
2414
pendingExecutionGroup ,
2399
2415
path ,
2400
2416
resolved ,
2401
- ) ,
2402
- ( error : unknown ) => ( {
2403
- pendingExecutionGroup,
2404
- path : pathToArray ( path ) ,
2405
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2406
- } ) ,
2417
+ ) ;
2418
+ } ,
2419
+ ( error : unknown ) => {
2420
+ incrementalContext . completed = true ;
2421
+ return {
2422
+ pendingExecutionGroup,
2423
+ path : pathToArray ( path ) ,
2424
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2425
+ } ;
2426
+ } ,
2407
2427
) ;
2408
2428
}
2409
2429
2430
+ incrementalContext . completed = true ;
2410
2431
return buildCompletedExecutionGroup (
2411
2432
incrementalContext . errors ,
2412
2433
pendingExecutionGroup ,
@@ -2461,7 +2482,7 @@ function buildSyncStreamItemQueue(
2461
2482
initialPath ,
2462
2483
initialItem ,
2463
2484
exeContext ,
2464
- { errors : undefined } ,
2485
+ { errors : undefined , completed : false } ,
2465
2486
fieldDetailsList ,
2466
2487
info ,
2467
2488
itemType ,
@@ -2492,7 +2513,7 @@ function buildSyncStreamItemQueue(
2492
2513
itemPath ,
2493
2514
value ,
2494
2515
exeContext ,
2495
- { errors : undefined } ,
2516
+ { errors : undefined , completed : false } ,
2496
2517
fieldDetailsList ,
2497
2518
info ,
2498
2519
itemType ,
@@ -2584,7 +2605,7 @@ async function getNextAsyncStreamItemResult(
2584
2605
itemPath ,
2585
2606
iteration . value ,
2586
2607
exeContext ,
2587
- { errors : undefined } ,
2608
+ { errors : undefined , completed : false } ,
2588
2609
fieldDetailsList ,
2589
2610
info ,
2590
2611
itemType ,
@@ -2631,11 +2652,16 @@ function completeStreamItem(
2631
2652
incrementalContext ,
2632
2653
new Map ( ) ,
2633
2654
) . then (
2634
- ( resolvedItem ) =>
2635
- buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ,
2636
- ( error : unknown ) => ( {
2637
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2638
- } ) ,
2655
+ ( resolvedItem ) => {
2656
+ incrementalContext . completed = true ;
2657
+ return buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ;
2658
+ } ,
2659
+ ( error : unknown ) => {
2660
+ incrementalContext . completed = true ;
2661
+ return {
2662
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2663
+ } ;
2664
+ } ,
2639
2665
) ;
2640
2666
}
2641
2667
@@ -2664,6 +2690,7 @@ function completeStreamItem(
2664
2690
result = { rawResult : null , incrementalDataRecords : undefined } ;
2665
2691
}
2666
2692
} catch ( error ) {
2693
+ incrementalContext . completed = true ;
2667
2694
return {
2668
2695
errors : withError ( incrementalContext . errors , error ) ,
2669
2696
} ;
@@ -2683,14 +2710,20 @@ function completeStreamItem(
2683
2710
return { rawResult : null , incrementalDataRecords : undefined } ;
2684
2711
} )
2685
2712
. then (
2686
- ( resolvedItem ) =>
2687
- buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ,
2688
- ( error : unknown ) => ( {
2689
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2690
- } ) ,
2713
+ ( resolvedItem ) => {
2714
+ incrementalContext . completed = true ;
2715
+ return buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ;
2716
+ } ,
2717
+ ( error : unknown ) => {
2718
+ incrementalContext . completed = true ;
2719
+ return {
2720
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2721
+ } ;
2722
+ } ,
2691
2723
) ;
2692
2724
}
2693
2725
2726
+ incrementalContext . completed = true ;
2694
2727
return buildStreamItemResult ( incrementalContext . errors , result ) ;
2695
2728
}
2696
2729
0 commit comments