@@ -329,12 +329,12 @@ ExecuteRootSelectionSet(variableValues, initialValue, objectType, selectionSet,
329
329
serial):
330
330
331
331
- If {serial} is not provided, initialize it to {false}.
332
- - Let {groupedFieldSet} and {newDeferUsages} be the result of
333
- {CollectFields(objectType, selectionSet, variableValues)}.
332
+ - Let {groupedFieldSet} be the result of {CollectFields(objectType,
333
+ selectionSet, variableValues)}.
334
334
- Let {executionPlan} be the result of {BuildExecutionPlan(groupedFieldSet)}.
335
335
- Let {data} and {incrementalDataRecords} be the result of
336
- {ExecuteExecutionPlan(newDeferUsages, executionPlan, objectType, initialValue,
337
- variableValues, serial)}.
336
+ {ExecuteExecutionPlan(executionPlan, objectType, initialValue, variableValues ,
337
+ serial)}.
338
338
- Let {errors} be the list of all _ field error_ raised while completing {data}.
339
339
- If {incrementalDataRecords} is empty, return an unordered map containing
340
340
{data} and {errors}.
@@ -405,11 +405,28 @@ GraphFromRecords(incrementalDataRecords, graph):
405
405
- Let {newGraph} be a new directed acyclic graph containing all of the nodes and
406
406
edges in {graph}.
407
407
- For each {incrementalDataRecord} of {incrementalDataRecords}:
408
+ - Let {deferUsageSet} be the Defer Usages incrementally completed by
409
+ {incrementalDataRecord} at {path}.
410
+ - For each {deferUsage} of {deferUsageSet}:
411
+ - If {newGraph} does not contain a Deferred Fragment node representing the
412
+ completion of {deferUsage} at {path}, reset {newGraph} to the result of
413
+ {GraphWithDeferredFragmentRecord(deferUsage, path, newGraph)}.
408
414
- Add {incrementalDataRecord} to {newGraph} as a new Pending Data node
409
- directed from the {pendingResults} that it completes, adding each of
410
- {pendingResults} to {newGraph} as a new node directed from its {parent},
411
- recursively adding each {parent} until {incrementalDataRecord} is connected
412
- to {newGraph}, or the {parent} is not defined.
415
+ directed from the {deferredFragments} that it completes.
416
+ - Return {newGraph}.
417
+
418
+ GraphWithDeferredFragmentRecord(deferUsage, path, graph):
419
+
420
+ - Let {parentDeferUsage} and {label} be the corresponding entries on
421
+ {deferUsage}.
422
+ - If {parentDeferUsage} is defined and {graph} does not contain a Deferred
423
+ Fragment node representing the completion of {parentDeferUsage} at {path}, let
424
+ {newGraph} be the result of {GraphWithDeferredFragmentRecord(parentDeferUsage,
425
+ path, newGraph)}; otherwise, let {newGraph} be a new directed acyclic graph
426
+ containing all of the nodes and edges in {graph}.
427
+ - Let {deferredFragment} be a new unordered map containing {path} and {label}.
428
+ - Add {deferredFragment} to {newGraph} as a new Deferred Fragment node directed
429
+ from {parent}.
413
430
- Return {newGraph}.
414
431
415
432
GetNonEmptyNewPending(graph):
@@ -454,8 +471,8 @@ GetIncrementalResult(graph, incremental, completed, pending):
454
471
455
472
GetIncrementalEntry(incrementalDataRecord, graph):
456
473
457
- - Let {deferredFragments} be the Deferred Fragments incrementally completed by
458
- {incrementalDataRecord} at {path}.
474
+ - Let {deferredFragments} be the Deferred Fragment nodes within {graph}
475
+ incrementally completed by {incrementalDataRecord} at {path}.
459
476
- Let {result} be the result of {incrementalDataRecord}.
460
477
- Let {data} and {errors} be the corresponding entries on {result}.
461
478
- Let {releasedDeferredFragments} be the members of {deferredFragments} that are
@@ -496,67 +513,48 @@ To execute a execution plan, the object value being evaluated and the object
496
513
type need to be known, as well as whether the non-deferred grouped field set
497
514
must be executed serially, or may be executed in parallel.
498
515
499
- ExecuteExecutionPlan(newDeferUsages, executionPlan, objectType, objectValue,
500
- variableValues, serial, path, deferUsageSet, deferMap ):
516
+ ExecuteExecutionPlan(executionPlan, objectType, objectValue, variableValues ,
517
+ serial, path, deferUsageSet):
501
518
502
519
- If {path} is not provided, initialize it to an empty list.
503
- - Let {newDeferMap} be the result of {GetNewDeferMap(newDeferUsages, path,
504
- deferMap)}.
505
520
- Let {groupedFieldSet} and {newGroupedFieldSets} be the corresponding entries
506
521
on {executionPlan}.
507
522
- Allowing for parallelization, perform the following steps:
508
523
- Let {data} and {nestedIncrementalDataRecords} be the result of running
509
524
{ExecuteGroupedFieldSet(groupedFieldSet, objectType, objectValue,
510
- variableValues, path, deferUsageSet, newDeferMap )} _ serially_ if {serial} is
511
- {true}, _ normally_ (allowing parallelization) otherwise.
525
+ variableValues, path, deferUsageSet)} _ serially_ if {serial} is {true},
526
+ _ normally_ (allowing parallelization) otherwise.
512
527
- Let {incrementalDataRecords} be the result of
513
528
{CollectExecutionGroups(objectType, objectValue, variableValues,
514
529
newGroupedFieldSets, path, newDeferMap)}.
515
530
- Append all items in {nestedIncrementalDataRecords} to
516
531
{incrementalDataRecords}.
517
532
- Return {data} and {incrementalDataRecords}.
518
533
519
- GetNewDeferMap(newDeferUsages, path, deferMap):
520
-
521
- - If {newDeferUsages} is empty, return {deferMap}:
522
- - Let {newDeferMap} be a new unordered map containing all entries in {deferMap}.
523
- - For each {deferUsage} in {newDeferUsages}:
524
- - Let {parentDeferUsage} and {label} be the corresponding entries on
525
- {deferUsage}.
526
- - Let {parent} be the entry in {deferMap} for {parentDeferUsage}.
527
- - Let {newDeferredFragment} be an unordered map containing {parent}, {path}
528
- and {label}.
529
- - Set the entry for {deferUsage} in {newDeferMap} to {newDeferredFragment}.
530
- - Return {newDeferMap}.
531
-
532
534
CollectExecutionGroups(objectType, objectValue, variableValues,
533
- newGroupedFieldSets, path, deferMap ):
535
+ newGroupedFieldSets, path):
534
536
535
537
- Initialize {incrementalDataRecords} to an empty list.
536
538
- For each {deferUsageSet} and {groupedFieldSet} in {newGroupedFieldSets}:
537
- - Let {deferredFragments} be an empty list.
538
- - For each {deferUsage} in {deferUsageSet}:
539
- - Let {deferredFragment} be the entry for {deferUsage} in {deferMap}.
540
- - Append {deferredFragment} to {deferredFragments}.
541
539
- Let {incrementalDataRecord} represent the future execution of
542
540
{ExecuteExecutionGroup(groupedFieldSet, objectType, objectValue,
543
- variableValues, deferredFragments, path, deferUsageSet, deferMap )},
544
- incrementally completing {deferredFragments } at {path}.
541
+ variableValues, path, deferUsageSet)}, incrementally completing
542
+ {deferUsageSet } at {path}.
545
543
- Append {incrementalDataRecord} to {incrementalDataRecords}.
546
544
- Schedule initiation of execution of {incrementalDataRecord} following any
547
545
implementation specific deferral.
548
546
- Return {incrementalDataRecords}.
549
547
550
548
Note: {incrementalDataRecord} can be safely initiated without blocking
551
- higher-priority data once any of {deferredFragments} are released as pending.
549
+ higher-priority data once any of {deferUsageSet} at {path} are released as
550
+ pending.
552
551
553
552
ExecuteExecutionGroup(groupedFieldSet, objectType, objectValue, variableValues,
554
- path, deferUsageSet, deferMap ):
553
+ path, deferUsageSet):
555
554
556
555
- Let {data} and {incrementalDataRecords} be the result of running
557
556
{ExecuteGroupedFieldSet(groupedFieldSet, objectType, objectValue,
558
- variableValues, path, deferUsageSet, deferMap)} _ normally_ (allowing
559
- parallelization).
557
+ variableValues, path, deferUsageSet)} _ normally_ (allowing parallelization).
560
558
- Let {errors} be the list of all _ field error_ raised while completing {data}.
561
559
- Return an unordered map containing {data}, {errors}, and
562
560
{incrementalDataRecords}.
@@ -571,7 +569,7 @@ Each represented field in the grouped field set produces an entry into a
571
569
response map.
572
570
573
571
ExecuteGroupedFieldSet(groupedFieldSet, objectType, objectValue, variableValues,
574
- path, deferUsageSet, deferMap ):
572
+ path, deferUsageSet):
575
573
576
574
- Initialize {resultMap} to an empty ordered map.
577
575
- Initialize {incrementalDataRecords} to an empty list.
@@ -583,7 +581,7 @@ path, deferUsageSet, deferMap):
583
581
- If {fieldType} is defined:
584
582
- Let {responseValue} and {fieldIncrementalDataRecords} be the result of
585
583
{ExecuteField(objectType, objectValue, fieldType, fields, variableValues,
586
- path, deferUsageSet, deferMap )}.
584
+ path, deferUsageSet)}.
587
585
- Set {responseValue} as the value for {responseKey} in {resultMap}.
588
586
- Append all items in {fieldIncrementalDataRecords} to
589
587
{incrementalDataRecords}.
@@ -747,6 +745,8 @@ Defer Usages contain the following information:
747
745
any, otherwise {undefined}.
748
746
- {parentDeferUsage}: a Defer Usage corresponding to the ` @defer ` directive
749
747
enclosing this ` @defer ` directive, if any, otherwise {undefined}.
748
+ - {depth}: the depth within the overall result corresponding to the deferred
749
+ fields.
750
750
751
751
The {parentDeferUsage} entry is used to build distinct Execution Groups as
752
752
discussed within the Execution Plan Generation section below.
@@ -761,18 +761,12 @@ A Grouped Field Set is an ordered map of keys to lists of Field Details. The
761
761
keys are the same as that of the response, the alias for the field, if defined,
762
762
otherwise the field name.
763
763
764
- The {CollectFields()} algorithm returns:
765
-
766
- - {groupedFieldSet}: the Grouped Field Set for the fields in the selection set.
767
- - {newDeferUsages}: a list of new Defer Usages encountered during this field
768
- collection.
769
-
770
- CollectFields(objectType, selectionSet, variableValues, deferUsage,
764
+ CollectFields(objectType, selectionSet, variableValues, deferUsage, depth,
771
765
visitedFragments):
772
766
767
+ - If {depth} is not provided, initialize it to {0}.
773
768
- If {visitedFragments} is not provided, initialize it to the empty set.
774
769
- Initialize {groupedFields} to an empty ordered map of lists.
775
- - Initialize {newDeferUsages} to an empty list.
776
770
- For each {selection} in {selectionSet}:
777
771
- If {selection} provides the directive ` @skip ` , let {skipDirective} be that
778
772
directive.
@@ -816,19 +810,18 @@ visitedFragments):
816
810
- If {deferDirective} is defined:
817
811
- Let {label} be the corresponding entry on {deferDirective}.
818
812
- Let {parentDeferUsage} be {deferUsage}.
819
- - Let {fragmentDeferUsage} be an unordered map containing {label} and
820
- {parentDeferUsage}.
813
+ - Let {fragmentDeferUsage} be an unordered map containing {label},
814
+ {parentDeferUsage}, and {depth} .
821
815
- Otherwise, let {fragmentDeferUsage} be {deferUsage}.
822
- - Let {fragmentGroupedFieldSet} and {fragmentNewDeferUsages} be the result
823
- of calling {CollectFields(objectType, fragmentSelectionSet,
824
- variableValues, fragmentDeferUsage , visitedFragments)}.
816
+ - Let {fragmentGroupedFieldSet} be the result of calling
817
+ {CollectFields(objectType, fragmentSelectionSet, variableValues ,
818
+ fragmentDeferUsage, depth , visitedFragments)}.
825
819
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
826
820
- Let {responseKey} be the response key shared by all fields in
827
821
{fragmentGroup}.
828
822
- Let {groupForResponseKey} be the list in {groupedFields} for
829
823
{responseKey}; if no such list exists, create it as an empty list.
830
824
- Append all items in {fragmentGroup} to {groupForResponseKey}.
831
- - Append all items in {fragmentNewDeferUsages} to {newDeferUsages}.
832
825
- If {selection} is an {InlineFragment}:
833
826
- Let {fragmentType} be the type condition on {selection}.
834
827
- If {fragmentType} is not {null} and {DoesFragmentTypeApply(objectType,
@@ -844,20 +837,19 @@ visitedFragments):
844
837
- If {deferDirective} is defined:
845
838
- Let {label} be the corresponding entry on {deferDirective}.
846
839
- Let {parentDeferUsage} be {deferUsage}.
847
- - Let {fragmentDeferUsage} be an unordered map containing {label} and
848
- {parentDeferUsage}.
840
+ - Let {fragmentDeferUsage} be an unordered map containing {label},
841
+ {parentDeferUsage}, and {depth} .
849
842
- Otherwise, let {fragmentDeferUsage} be {deferUsage}.
850
- - Let {fragmentGroupedFieldSet} and {fragmentNewDeferUsages} be the result
851
- of calling {CollectFields(objectType, fragmentSelectionSet,
852
- variableValues, fragmentDeferUsage , visitedFragments)}.
843
+ - Let {fragmentGroupedFieldSet} be the result of calling
844
+ {CollectFields(objectType, fragmentSelectionSet, variableValues ,
845
+ fragmentDeferUsage, depth , visitedFragments)}.
853
846
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
854
847
- Let {responseKey} be the response key shared by all fields in
855
848
{fragmentGroup}.
856
849
- Let {groupForResponseKey} be the list in {groupedFields} for
857
850
{responseKey}; if no such list exists, create it as an empty list.
858
851
- Append all items in {fragmentGroup} to {groupForResponseKey}.
859
- - Append all items in {fragmentNewDeferUsages} to {newDeferUsages}.
860
- - Return {groupedFields} and {newDeferUsages}.
852
+ - Return {groupedFields}.
861
853
862
854
DoesFragmentTypeApply(objectType, fragmentType):
863
855
@@ -928,7 +920,7 @@ finally completes that value either by recursively executing another selection
928
920
set or coercing a scalar value.
929
921
930
922
ExecuteField(objectType, objectValue, fieldType, fieldDetailsList,
931
- variableValues, path, deferUsageSet, deferMap ):
923
+ variableValues, path, deferUsageSet):
932
924
933
925
- Let {fieldDetails} be the first entry in {fieldDetailsList}.
934
926
- Let {field} be the corresponding entry on {fieldDetails}.
@@ -939,7 +931,7 @@ variableValues, path, deferUsageSet, deferMap):
939
931
- Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName,
940
932
argumentValues)}.
941
933
- Return the result of {CompleteValue(fieldType, fields, resolvedValue,
942
- variableValues, path, deferUsageSet, deferMap )}.
934
+ variableValues, path, deferUsageSet)}.
943
935
944
936
### Coercing Field Arguments
945
937
@@ -1027,7 +1019,7 @@ the expected return type. If the return type is another Object type, then the
1027
1019
field execution process continues recursively.
1028
1020
1029
1021
CompleteValue(fieldType, fieldDetailsList, result, variableValues, path,
1030
- deferUsageSet, deferMap ):
1022
+ deferUsageSet):
1031
1023
1032
1024
- If the {fieldType} is a Non-Null type:
1033
1025
- Let {innerType} be the inner type of {fieldType}.
@@ -1041,23 +1033,24 @@ deferUsageSet, deferMap):
1041
1033
- If {result} is not a collection of values, raise a _ field error_ .
1042
1034
- Let {innerType} be the inner type of {fieldType}.
1043
1035
- Return the result of {CompleteListValue(innerType, fieldDetailsList, result,
1044
- variableValues, path, deferUsageSet, deferMap )}.
1036
+ variableValues, path, deferUsageSet)}.
1045
1037
- If {fieldType} is a Scalar or Enum type:
1046
1038
- Return the result of {CoerceResult(fieldType, result)}.
1047
1039
- If {fieldType} is an Object, Interface, or Union type:
1048
1040
- If {fieldType} is an Object type.
1049
1041
- Let {objectType} be {fieldType}.
1050
1042
- Otherwise if {fieldType} is an Interface or Union type.
1051
1043
- Let {objectType} be {ResolveAbstractType(fieldType, result)}.
1052
- - Let {groupedFieldSet} and {newDeferUsages} be the result of calling
1053
- {CollectSubfields(objectType, fieldDetailsList, variableValues)}.
1044
+ - Let {depth} be the length of {path}.
1045
+ - Let {groupedFieldSet} be the result of calling {CollectSubfields(objectType,
1046
+ fieldDetailsList, variableValues, depth)}.
1054
1047
- Let {executionPlan} be the result of {BuildExecutionPlan(groupedFieldSet,
1055
1048
deferUsageSet)}.
1056
- - Return the result of {ExecuteExecutionPlan(newDeferUsages, executionPlan ,
1057
- objectType, result, variableValues, false, path, deferUsageSet, deferMap )}.
1049
+ - Return the result of {ExecuteExecutionPlan(executionPlan, objectType ,
1050
+ result, variableValues, false, path, deferUsageSet)}.
1058
1051
1059
1052
CompleteListValue(innerType, fieldDetailsList, result, variableValues, path,
1060
- deferUsageSet, deferMap ):
1053
+ deferUsageSet):
1061
1054
1062
1055
- Initialize {items} and {incrementalDataRecords} to empty lists.
1063
1056
- Let {index} be {0}.
@@ -1136,22 +1129,20 @@ sub-selections.
1136
1129
After resolving the value for ` me ` , the selection sets are merged together so
1137
1130
` firstName ` and ` lastName ` can be resolved for one value.
1138
1131
1139
- CollectSubfields(objectType, fieldDetailsList, variableValues):
1132
+ CollectSubfields(objectType, fieldDetailsList, variableValues, depth ):
1140
1133
1141
1134
- Initialize {groupedFieldSet} to an empty ordered map of lists.
1142
- - Initialize {newDeferUsages} to an empty list.
1143
1135
- For each {fieldDetails} in {fieldDetailsList}:
1144
1136
- Let {field} and {deferUsage} be the corresponding entries on {fieldDetails}.
1145
1137
- Let {fieldSelectionSet} be the selection set of {field}.
1146
1138
- If {fieldSelectionSet} is null or empty, continue to the next field.
1147
- - Let {subGroupedFieldSet} and {subNewDeferUsages} be the result of
1148
- {CollectFields(objectType, fieldSelectionSet, variableValues, deferUsage)}.
1139
+ - Let {subGroupedFieldSet} be the result of {CollectFields(objectType,
1140
+ fieldSelectionSet, variableValues, deferUsage, depth )}.
1149
1141
- For each {subGroupedFieldSet} as {responseKey} and {subfields}:
1150
1142
- Let {groupForResponseKey} be the list in {groupedFieldSet} for
1151
1143
{responseKey}; if no such list exists, create it as an empty list.
1152
1144
- Append all fields in {subfields} to {groupForResponseKey}.
1153
- - Append all defer usages in {subNewDeferUsages} to {newDeferUsages}.
1154
- - Return {groupedFieldSet} and {newDeferUsages}.
1145
+ - Return {groupedFieldSet}.
1155
1146
1156
1147
### Handling Field Errors
1157
1148
0 commit comments