Skip to content

Commit 6e39947

Browse files
committed
refactor execution plan functions to match spec
moves simplest case inside the execute[Root|Sub]ExecutionPlan() functions to better match proposed spec edits orders function in call order, moving executeSubExecutionPlan down closer to where it is used
1 parent d59c725 commit 6e39947

File tree

1 file changed

+158
-114
lines changed

1 file changed

+158
-114
lines changed

src/execution/execute.ts

Lines changed: 158 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
333333
);
334334
}
335335

336-
const collectedFields = collectFields(
336+
const { groupedFieldSet, newDeferUsages } = collectFields(
337337
schema,
338338
fragments,
339339
variableValues,
@@ -342,24 +342,14 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
342342
hideSuggestions,
343343
);
344344

345-
const { groupedFieldSet, newDeferUsages } = collectedFields;
346-
const graphqlWrappedResult =
347-
newDeferUsages.length === 0
348-
? executeRootGroupedFieldSet(
349-
exeContext,
350-
operation.operation,
351-
rootType,
352-
rootValue,
353-
groupedFieldSet,
354-
undefined,
355-
)
356-
: executeExecutionPlan(
357-
exeContext,
358-
rootType,
359-
rootValue,
360-
newDeferUsages,
361-
buildExecutionPlan(groupedFieldSet),
362-
);
345+
const graphqlWrappedResult = executeRootExecutionPlan(
346+
exeContext,
347+
operation.operation,
348+
rootType,
349+
rootValue,
350+
groupedFieldSet,
351+
newDeferUsages,
352+
);
363353

364354
if (isPromise(graphqlWrappedResult)) {
365355
return graphqlWrappedResult.then(
@@ -376,78 +366,6 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
376366
}
377367
}
378368

379-
function executeExecutionPlan(
380-
exeContext: ExecutionContext,
381-
returnType: GraphQLObjectType,
382-
sourceValue: unknown,
383-
newDeferUsages: ReadonlyArray<DeferUsage>,
384-
executionPlan: ExecutionPlan,
385-
path?: Path | undefined,
386-
incrementalContext?: IncrementalContext | undefined,
387-
deferMap?: ReadonlyMap<DeferUsage, DeferredFragmentRecord> | undefined,
388-
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
389-
const newDeferMap = getNewDeferMap(newDeferUsages, deferMap, path);
390-
391-
const { groupedFieldSet, newGroupedFieldSets } = executionPlan;
392-
393-
const graphqlWrappedResult = executeFields(
394-
exeContext,
395-
returnType,
396-
sourceValue,
397-
path,
398-
groupedFieldSet,
399-
incrementalContext,
400-
newDeferMap,
401-
);
402-
403-
if (newGroupedFieldSets.size > 0) {
404-
const newPendingExecutionGroups = collectExecutionGroups(
405-
exeContext,
406-
returnType,
407-
sourceValue,
408-
path,
409-
incrementalContext?.deferUsageSet,
410-
newGroupedFieldSets,
411-
newDeferMap,
412-
);
413-
414-
return withNewExecutionGroups(
415-
graphqlWrappedResult,
416-
newPendingExecutionGroups,
417-
);
418-
}
419-
return graphqlWrappedResult;
420-
}
421-
422-
function withNewExecutionGroups(
423-
result: PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>>,
424-
newPendingExecutionGroups: ReadonlyArray<PendingExecutionGroup>,
425-
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
426-
if (isPromise(result)) {
427-
return result.then((resolved) => {
428-
addIncrementalDataRecords(resolved, newPendingExecutionGroups);
429-
return resolved;
430-
});
431-
}
432-
433-
addIncrementalDataRecords(result, newPendingExecutionGroups);
434-
return result;
435-
}
436-
437-
function addIncrementalDataRecords(
438-
graphqlWrappedResult: GraphQLWrappedResult<unknown>,
439-
incrementalDataRecords: ReadonlyArray<IncrementalDataRecord> | undefined,
440-
): void {
441-
if (incrementalDataRecords === undefined) {
442-
return;
443-
}
444-
if (graphqlWrappedResult.incrementalDataRecords === undefined) {
445-
graphqlWrappedResult.incrementalDataRecords = [...incrementalDataRecords];
446-
} else {
447-
graphqlWrappedResult.incrementalDataRecords.push(...incrementalDataRecords);
448-
}
449-
}
450-
451369
function withError(
452370
errors: Array<GraphQLError> | undefined,
453371
error: GraphQLError,
@@ -603,6 +521,73 @@ export function validateExecutionArgs(
603521
};
604522
}
605523

524+
function executeRootExecutionPlan(
525+
exeContext: ExecutionContext,
526+
operation: OperationTypeNode,
527+
rootType: GraphQLObjectType,
528+
rootValue: unknown,
529+
originalGroupedFieldSet: GroupedFieldSet,
530+
newDeferUsages: ReadonlyArray<DeferUsage>,
531+
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
532+
if (newDeferUsages.length === 0) {
533+
return executeRootGroupedFieldSet(
534+
exeContext,
535+
operation,
536+
rootType,
537+
rootValue,
538+
originalGroupedFieldSet,
539+
undefined,
540+
);
541+
}
542+
const newDeferMap = getNewDeferMap(newDeferUsages, undefined, undefined);
543+
544+
const { groupedFieldSet, newGroupedFieldSets } = buildExecutionPlan(
545+
originalGroupedFieldSet,
546+
);
547+
548+
const graphqlWrappedResult = executeRootGroupedFieldSet(
549+
exeContext,
550+
operation,
551+
rootType,
552+
rootValue,
553+
groupedFieldSet,
554+
newDeferMap,
555+
);
556+
557+
if (newGroupedFieldSets.size > 0) {
558+
const newPendingExecutionGroups = collectExecutionGroups(
559+
exeContext,
560+
rootType,
561+
rootValue,
562+
undefined,
563+
undefined,
564+
newGroupedFieldSets,
565+
newDeferMap,
566+
);
567+
568+
return withNewExecutionGroups(
569+
graphqlWrappedResult,
570+
newPendingExecutionGroups,
571+
);
572+
}
573+
return graphqlWrappedResult;
574+
}
575+
576+
function withNewExecutionGroups(
577+
result: PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>>,
578+
newPendingExecutionGroups: ReadonlyArray<PendingExecutionGroup>,
579+
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
580+
if (isPromise(result)) {
581+
return result.then((resolved) => {
582+
addIncrementalDataRecords(resolved, newPendingExecutionGroups);
583+
return resolved;
584+
});
585+
}
586+
587+
addIncrementalDataRecords(result, newPendingExecutionGroups);
588+
return result;
589+
}
590+
606591
function executeRootGroupedFieldSet(
607592
exeContext: ExecutionContext,
608593
operation: OperationTypeNode,
@@ -714,6 +699,20 @@ function executeFieldsSerially(
714699
);
715700
}
716701

702+
function addIncrementalDataRecords(
703+
graphqlWrappedResult: GraphQLWrappedResult<unknown>,
704+
incrementalDataRecords: ReadonlyArray<IncrementalDataRecord> | undefined,
705+
): void {
706+
if (incrementalDataRecords === undefined) {
707+
return;
708+
}
709+
if (graphqlWrappedResult.incrementalDataRecords === undefined) {
710+
graphqlWrappedResult.incrementalDataRecords = [...incrementalDataRecords];
711+
} else {
712+
graphqlWrappedResult.incrementalDataRecords.push(...incrementalDataRecords);
713+
}
714+
}
715+
717716
/**
718717
* Implements the "Executing selection sets" section of the spec
719718
* for fields that may be executed in parallel.
@@ -1871,29 +1870,74 @@ function collectAndExecuteSubfields(
18711870
fieldDetailsList,
18721871
);
18731872
const { groupedFieldSet, newDeferUsages } = collectedSubfields;
1874-
return deferMap === undefined && newDeferUsages.length === 0
1875-
? executeFields(
1876-
exeContext,
1877-
returnType,
1878-
result,
1879-
path,
1880-
groupedFieldSet,
1881-
incrementalContext,
1882-
undefined,
1883-
)
1884-
: executeExecutionPlan(
1885-
exeContext,
1886-
returnType,
1887-
result,
1888-
newDeferUsages,
1889-
buildSubExecutionPlan(
1890-
groupedFieldSet,
1891-
incrementalContext?.deferUsageSet,
1892-
),
1893-
path,
1894-
incrementalContext,
1895-
deferMap,
1896-
);
1873+
return executeSubExecutionPlan(
1874+
exeContext,
1875+
returnType,
1876+
result,
1877+
groupedFieldSet,
1878+
newDeferUsages,
1879+
path,
1880+
incrementalContext,
1881+
deferMap,
1882+
);
1883+
}
1884+
1885+
function executeSubExecutionPlan(
1886+
exeContext: ExecutionContext,
1887+
returnType: GraphQLObjectType,
1888+
sourceValue: unknown,
1889+
originalGroupedFieldSet: GroupedFieldSet,
1890+
newDeferUsages: ReadonlyArray<DeferUsage>,
1891+
path?: Path | undefined,
1892+
incrementalContext?: IncrementalContext | undefined,
1893+
deferMap?: ReadonlyMap<DeferUsage, DeferredFragmentRecord> | undefined,
1894+
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
1895+
if (deferMap === undefined && newDeferUsages.length === 0) {
1896+
return executeFields(
1897+
exeContext,
1898+
returnType,
1899+
sourceValue,
1900+
path,
1901+
originalGroupedFieldSet,
1902+
incrementalContext,
1903+
deferMap,
1904+
);
1905+
}
1906+
1907+
const newDeferMap = getNewDeferMap(newDeferUsages, deferMap, path);
1908+
1909+
const { groupedFieldSet, newGroupedFieldSets } = buildSubExecutionPlan(
1910+
originalGroupedFieldSet,
1911+
incrementalContext?.deferUsageSet,
1912+
);
1913+
1914+
const graphqlWrappedResult = executeFields(
1915+
exeContext,
1916+
returnType,
1917+
sourceValue,
1918+
path,
1919+
groupedFieldSet,
1920+
incrementalContext,
1921+
newDeferMap,
1922+
);
1923+
1924+
if (newGroupedFieldSets.size > 0) {
1925+
const newPendingExecutionGroups = collectExecutionGroups(
1926+
exeContext,
1927+
returnType,
1928+
sourceValue,
1929+
path,
1930+
incrementalContext?.deferUsageSet,
1931+
newGroupedFieldSets,
1932+
newDeferMap,
1933+
);
1934+
1935+
return withNewExecutionGroups(
1936+
graphqlWrappedResult,
1937+
newPendingExecutionGroups,
1938+
);
1939+
}
1940+
return graphqlWrappedResult;
18971941
}
18981942

18991943
function buildSubExecutionPlan(

0 commit comments

Comments
 (0)