@@ -281,52 +281,26 @@ function executeOperation(
281281 rootType ,
282282 operation ,
283283 ) ;
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 ( ) ) ;
303284
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+ ) ;
323303
324- graphqlWrappedResult = withNewExecutionGroups (
325- graphqlWrappedResult ,
326- newPendingExecutionGroups ,
327- ) ;
328- }
329- }
330304 if ( isPromise ( graphqlWrappedResult ) ) {
331305 return graphqlWrappedResult . then (
332306 ( resolved ) => buildDataResponse ( exeContext , resolved [ 0 ] , resolved [ 1 ] ) ,
@@ -346,6 +320,49 @@ function executeOperation(
346320 }
347321}
348322
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+
349366function withNewExecutionGroups (
350367 result : PromiseOrValue < GraphQLWrappedResult < ObjMap < unknown > > > ,
351368 newPendingExecutionGroups : ReadonlyArray < PendingExecutionGroup > ,
@@ -1663,21 +1680,14 @@ function invalidReturnTypeError(
16631680 *
16641681 * Note: As defer directives may be used with operations returning lists,
16651682 * 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- *
16751683 */
1676- function addNewDeferredFragments (
1684+ function getNewDeferMap (
16771685 newDeferUsages : ReadonlyArray < DeferUsage > ,
1678- newDeferMap : Map < DeferUsage , DeferredFragmentRecord > ,
1686+ deferMap ?: ReadonlyMap < DeferUsage , DeferredFragmentRecord > | undefined ,
16791687 path ?: Path | undefined ,
16801688) : ReadonlyMap < DeferUsage , DeferredFragmentRecord > {
1689+ const newDeferMap = new Map ( deferMap ) ;
1690+
16811691 // For each new deferUsage object:
16821692 for ( const newDeferUsage of newDeferUsages ) {
16831693 const parentDeferUsage = newDeferUsage . parentDeferUsage ;
@@ -1724,56 +1734,30 @@ function collectAndExecuteSubfields(
17241734 returnType ,
17251735 fieldGroup ,
17261736 ) ;
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+ ) ;
17771761}
17781762
17791763function buildSubExecutionPlan (
0 commit comments