@@ -281,52 +281,26 @@ function executeOperation(
281
281
rootType ,
282
282
operation ,
283
283
) ;
284
- let groupedFieldSet = collectedFields . groupedFieldSet ;
285
- const newDeferUsages = collectedFields . newDeferUsages ;
286
- let graphqlWrappedResult : PromiseOrValue <
287
- GraphQLWrappedResult < ObjMap < unknown > >
288
- > ;
289
- if ( newDeferUsages . length === 0 ) {
290
- graphqlWrappedResult = executeRootGroupedFieldSet (
291
- exeContext ,
292
- operation . operation ,
293
- rootType ,
294
- rootValue ,
295
- groupedFieldSet ,
296
- undefined ,
297
- ) ;
298
- } else {
299
- const executionPlan = buildExecutionPlan ( groupedFieldSet ) ;
300
- groupedFieldSet = executionPlan . groupedFieldSet ;
301
- const newGroupedFieldSets = executionPlan . newGroupedFieldSets ;
302
- const newDeferMap = addNewDeferredFragments ( newDeferUsages , new Map ( ) ) ;
303
284
304
- graphqlWrappedResult = executeRootGroupedFieldSet (
305
- exeContext ,
306
- operation . operation ,
307
- rootType ,
308
- rootValue ,
309
- groupedFieldSet ,
310
- newDeferMap ,
311
- ) ;
312
-
313
- if ( newGroupedFieldSets . size > 0 ) {
314
- const newPendingExecutionGroups = collectExecutionGroups (
315
- exeContext ,
316
- rootType ,
317
- rootValue ,
318
- undefined ,
319
- undefined ,
320
- newGroupedFieldSets ,
321
- newDeferMap ,
322
- ) ;
285
+ const { groupedFieldSet, newDeferUsages } = collectedFields ;
286
+ const graphqlWrappedResult =
287
+ newDeferUsages . length === 0
288
+ ? executeRootGroupedFieldSet (
289
+ exeContext ,
290
+ operation . operation ,
291
+ rootType ,
292
+ rootValue ,
293
+ groupedFieldSet ,
294
+ undefined ,
295
+ )
296
+ : executeExecutionPlan (
297
+ exeContext ,
298
+ rootType ,
299
+ rootValue ,
300
+ newDeferUsages ,
301
+ buildExecutionPlan ( groupedFieldSet ) ,
302
+ ) ;
323
303
324
- graphqlWrappedResult = withNewExecutionGroups (
325
- graphqlWrappedResult ,
326
- newPendingExecutionGroups ,
327
- ) ;
328
- }
329
- }
330
304
if ( isPromise ( graphqlWrappedResult ) ) {
331
305
return graphqlWrappedResult . then (
332
306
( resolved ) => buildDataResponse ( exeContext , resolved [ 0 ] , resolved [ 1 ] ) ,
@@ -346,6 +320,49 @@ function executeOperation(
346
320
}
347
321
}
348
322
323
+ function executeExecutionPlan (
324
+ exeContext : ExecutionContext ,
325
+ returnType : GraphQLObjectType ,
326
+ sourceValue : unknown ,
327
+ newDeferUsages : ReadonlyArray < DeferUsage > ,
328
+ executionPlan : ExecutionPlan ,
329
+ path ?: Path | undefined ,
330
+ incrementalContext ?: IncrementalContext | undefined ,
331
+ deferMap ?: ReadonlyMap < DeferUsage , DeferredFragmentRecord > | undefined ,
332
+ ) : PromiseOrValue < GraphQLWrappedResult < ObjMap < unknown > > > {
333
+ const newDeferMap = getNewDeferMap ( newDeferUsages , deferMap , path ) ;
334
+
335
+ const { groupedFieldSet, newGroupedFieldSets } = executionPlan ;
336
+
337
+ const graphqlWrappedResult = executeFields (
338
+ exeContext ,
339
+ returnType ,
340
+ sourceValue ,
341
+ path ,
342
+ groupedFieldSet ,
343
+ incrementalContext ,
344
+ newDeferMap ,
345
+ ) ;
346
+
347
+ if ( newGroupedFieldSets . size > 0 ) {
348
+ const newPendingExecutionGroups = collectExecutionGroups (
349
+ exeContext ,
350
+ returnType ,
351
+ sourceValue ,
352
+ path ,
353
+ incrementalContext ?. deferUsageSet ,
354
+ newGroupedFieldSets ,
355
+ newDeferMap ,
356
+ ) ;
357
+
358
+ return withNewExecutionGroups (
359
+ graphqlWrappedResult ,
360
+ newPendingExecutionGroups ,
361
+ ) ;
362
+ }
363
+ return graphqlWrappedResult ;
364
+ }
365
+
349
366
function withNewExecutionGroups (
350
367
result : PromiseOrValue < GraphQLWrappedResult < ObjMap < unknown > > > ,
351
368
newPendingExecutionGroups : ReadonlyArray < PendingExecutionGroup > ,
@@ -1663,21 +1680,14 @@ function invalidReturnTypeError(
1663
1680
*
1664
1681
* Note: As defer directives may be used with operations returning lists,
1665
1682
* a DeferUsage object may correspond to many DeferredFragmentRecords.
1666
- *
1667
- * DeferredFragmentRecord creation includes the following steps:
1668
- * 1. The new DeferredFragmentRecord is instantiated at the given path.
1669
- * 2. The parent result record is calculated from the given incremental data
1670
- * record.
1671
- * 3. The IncrementalPublisher is notified that a new DeferredFragmentRecord
1672
- * with the calculated parent has been added; the record will be released only
1673
- * after the parent has completed.
1674
- *
1675
1683
*/
1676
- function addNewDeferredFragments (
1684
+ function getNewDeferMap (
1677
1685
newDeferUsages : ReadonlyArray < DeferUsage > ,
1678
- newDeferMap : Map < DeferUsage , DeferredFragmentRecord > ,
1686
+ deferMap ?: ReadonlyMap < DeferUsage , DeferredFragmentRecord > | undefined ,
1679
1687
path ?: Path | undefined ,
1680
1688
) : ReadonlyMap < DeferUsage , DeferredFragmentRecord > {
1689
+ const newDeferMap = new Map ( deferMap ) ;
1690
+
1681
1691
// For each new deferUsage object:
1682
1692
for ( const newDeferUsage of newDeferUsages ) {
1683
1693
const parentDeferUsage = newDeferUsage . parentDeferUsage ;
@@ -1724,56 +1734,30 @@ function collectAndExecuteSubfields(
1724
1734
returnType ,
1725
1735
fieldGroup ,
1726
1736
) ;
1727
- let groupedFieldSet = collectedSubfields . groupedFieldSet ;
1728
- const newDeferUsages = collectedSubfields . newDeferUsages ;
1729
- if ( deferMap === undefined && newDeferUsages . length === 0 ) {
1730
- return executeFields (
1731
- exeContext ,
1732
- returnType ,
1733
- result ,
1734
- path ,
1735
- groupedFieldSet ,
1736
- incrementalContext ,
1737
- undefined ,
1738
- ) ;
1739
- }
1740
- const subExecutionPlan = buildSubExecutionPlan (
1741
- groupedFieldSet ,
1742
- incrementalContext ?. deferUsageSet ,
1743
- ) ;
1744
-
1745
- groupedFieldSet = subExecutionPlan . groupedFieldSet ;
1746
- const newGroupedFieldSets = subExecutionPlan . newGroupedFieldSets ;
1747
- const newDeferMap = addNewDeferredFragments (
1748
- newDeferUsages ,
1749
- new Map ( deferMap ) ,
1750
- path ,
1751
- ) ;
1752
-
1753
- const subFields = executeFields (
1754
- exeContext ,
1755
- returnType ,
1756
- result ,
1757
- path ,
1758
- groupedFieldSet ,
1759
- incrementalContext ,
1760
- newDeferMap ,
1761
- ) ;
1762
-
1763
- if ( newGroupedFieldSets . size > 0 ) {
1764
- const newPendingExecutionGroups = collectExecutionGroups (
1765
- exeContext ,
1766
- returnType ,
1767
- result ,
1768
- path ,
1769
- incrementalContext ?. deferUsageSet ,
1770
- newGroupedFieldSets ,
1771
- newDeferMap ,
1772
- ) ;
1773
-
1774
- return withNewExecutionGroups ( subFields , newPendingExecutionGroups ) ;
1775
- }
1776
- return subFields ;
1737
+ const { groupedFieldSet, newDeferUsages } = collectedSubfields ;
1738
+ return deferMap === undefined && newDeferUsages . length === 0
1739
+ ? executeFields (
1740
+ exeContext ,
1741
+ returnType ,
1742
+ result ,
1743
+ path ,
1744
+ groupedFieldSet ,
1745
+ incrementalContext ,
1746
+ undefined ,
1747
+ )
1748
+ : executeExecutionPlan (
1749
+ exeContext ,
1750
+ returnType ,
1751
+ result ,
1752
+ newDeferUsages ,
1753
+ buildSubExecutionPlan (
1754
+ groupedFieldSet ,
1755
+ incrementalContext ?. deferUsageSet ,
1756
+ ) ,
1757
+ path ,
1758
+ incrementalContext ,
1759
+ deferMap ,
1760
+ ) ;
1777
1761
}
1778
1762
1779
1763
function buildSubExecutionPlan (
0 commit comments