@@ -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 {
@@ -369,8 +372,12 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
369
372
370
373
if ( isPromise ( graphqlWrappedResult ) ) {
371
374
return graphqlWrappedResult . then (
372
- ( resolved ) => buildDataResponse ( exeContext , resolved ) ,
375
+ ( resolved ) => {
376
+ exeContext . completed = true ;
377
+ return buildDataResponse ( exeContext , resolved ) ;
378
+ } ,
373
379
( error : unknown ) => {
380
+ exeContext . completed = true ;
374
381
exeContext . promiseCanceller ?. disconnect ( ) ;
375
382
return {
376
383
data : null ,
@@ -379,8 +386,10 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
379
386
} ,
380
387
) ;
381
388
}
389
+ exeContext . completed = true ;
382
390
return buildDataResponse ( exeContext , graphqlWrappedResult ) ;
383
391
} catch ( error ) {
392
+ exeContext . completed = true ;
384
393
// TODO: add test case for synchronous null bubbling to root with cancellation
385
394
/* c8 ignore next */
386
395
exeContext . promiseCanceller ?. disconnect ( ) ;
@@ -1761,6 +1770,10 @@ function completeObjectValue(
1761
1770
incrementalContext : IncrementalContext | undefined ,
1762
1771
deferMap : ReadonlyMap < DeferUsage , DeferredFragmentRecord > | undefined ,
1763
1772
) : PromiseOrValue < GraphQLWrappedResult < ObjMap < unknown > > > {
1773
+ if ( ( incrementalContext ?? exeContext ) . completed ) {
1774
+ throw new Error ( 'Completed, aborting.' ) ;
1775
+ }
1776
+
1764
1777
// If there is an isTypeOf predicate function, call it with the
1765
1778
// current result. If isTypeOf returns false, then raise an error rather
1766
1779
// than continuing execution.
@@ -2280,6 +2293,7 @@ function collectExecutionGroups(
2280
2293
groupedFieldSet ,
2281
2294
{
2282
2295
errors : undefined ,
2296
+ completed : false ,
2283
2297
deferUsageSet,
2284
2298
} ,
2285
2299
deferMap ,
@@ -2339,6 +2353,7 @@ function executeExecutionGroup(
2339
2353
deferMap ,
2340
2354
) ;
2341
2355
} catch ( error ) {
2356
+ incrementalContext . completed = true ;
2342
2357
return {
2343
2358
pendingExecutionGroup,
2344
2359
path : pathToArray ( path ) ,
@@ -2348,21 +2363,27 @@ function executeExecutionGroup(
2348
2363
2349
2364
if ( isPromise ( result ) ) {
2350
2365
return result . then (
2351
- ( resolved ) =>
2352
- buildCompletedExecutionGroup (
2366
+ ( resolved ) => {
2367
+ incrementalContext . completed = true ;
2368
+ return buildCompletedExecutionGroup (
2353
2369
incrementalContext . errors ,
2354
2370
pendingExecutionGroup ,
2355
2371
path ,
2356
2372
resolved ,
2357
- ) ,
2358
- ( error : unknown ) => ( {
2359
- pendingExecutionGroup,
2360
- path : pathToArray ( path ) ,
2361
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2362
- } ) ,
2373
+ ) ;
2374
+ } ,
2375
+ ( error : unknown ) => {
2376
+ incrementalContext . completed = true ;
2377
+ return {
2378
+ pendingExecutionGroup,
2379
+ path : pathToArray ( path ) ,
2380
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2381
+ } ;
2382
+ } ,
2363
2383
) ;
2364
2384
}
2365
2385
2386
+ incrementalContext . completed = true ;
2366
2387
return buildCompletedExecutionGroup (
2367
2388
incrementalContext . errors ,
2368
2389
pendingExecutionGroup ,
@@ -2417,7 +2438,7 @@ function buildSyncStreamItemQueue(
2417
2438
initialPath ,
2418
2439
initialItem ,
2419
2440
exeContext ,
2420
- { errors : undefined } ,
2441
+ { errors : undefined , completed : false } ,
2421
2442
fieldDetailsList ,
2422
2443
info ,
2423
2444
itemType ,
@@ -2448,7 +2469,7 @@ function buildSyncStreamItemQueue(
2448
2469
itemPath ,
2449
2470
value ,
2450
2471
exeContext ,
2451
- { errors : undefined } ,
2472
+ { errors : undefined , completed : false } ,
2452
2473
fieldDetailsList ,
2453
2474
info ,
2454
2475
itemType ,
@@ -2540,7 +2561,7 @@ async function getNextAsyncStreamItemResult(
2540
2561
itemPath ,
2541
2562
iteration . value ,
2542
2563
exeContext ,
2543
- { errors : undefined } ,
2564
+ { errors : undefined , completed : false } ,
2544
2565
fieldDetailsList ,
2545
2566
info ,
2546
2567
itemType ,
@@ -2587,11 +2608,16 @@ function completeStreamItem(
2587
2608
incrementalContext ,
2588
2609
new Map ( ) ,
2589
2610
) . then (
2590
- ( resolvedItem ) =>
2591
- buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ,
2592
- ( error : unknown ) => ( {
2593
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2594
- } ) ,
2611
+ ( resolvedItem ) => {
2612
+ incrementalContext . completed = true ;
2613
+ return buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ;
2614
+ } ,
2615
+ ( error : unknown ) => {
2616
+ incrementalContext . completed = true ;
2617
+ return {
2618
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2619
+ } ;
2620
+ } ,
2595
2621
) ;
2596
2622
}
2597
2623
@@ -2620,6 +2646,7 @@ function completeStreamItem(
2620
2646
result = { rawResult : null , incrementalDataRecords : undefined } ;
2621
2647
}
2622
2648
} catch ( error ) {
2649
+ incrementalContext . completed = true ;
2623
2650
return {
2624
2651
errors : withError ( incrementalContext . errors , error ) ,
2625
2652
} ;
@@ -2639,14 +2666,20 @@ function completeStreamItem(
2639
2666
return { rawResult : null , incrementalDataRecords : undefined } ;
2640
2667
} )
2641
2668
. then (
2642
- ( resolvedItem ) =>
2643
- buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ,
2644
- ( error : unknown ) => ( {
2645
- errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2646
- } ) ,
2669
+ ( resolvedItem ) => {
2670
+ incrementalContext . completed = true ;
2671
+ return buildStreamItemResult ( incrementalContext . errors , resolvedItem ) ;
2672
+ } ,
2673
+ ( error : unknown ) => {
2674
+ incrementalContext . completed = true ;
2675
+ return {
2676
+ errors : withError ( incrementalContext . errors , error as GraphQLError ) ,
2677
+ } ;
2678
+ } ,
2647
2679
) ;
2648
2680
}
2649
2681
2682
+ incrementalContext . completed = true ;
2650
2683
return buildStreamItemResult ( incrementalContext . errors , result ) ;
2651
2684
}
2652
2685
0 commit comments