@@ -136,7 +136,9 @@ ExecuteQuery(query, schema, variableValues, initialValue):
136
136
- Let {queryType} be the root Query type in {schema}.
137
137
- Assert: {queryType} is an Object type.
138
138
- Let {selectionSet} be the top level Selection Set in {query}.
139
- - Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
139
+ - Let {groupedFieldSet} and {deferredGroupedFieldsList} be the result of
140
+ {CollectRootFields(queryType, selectionSet, variableValues)}.
141
+ - Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet,
140
142
queryType, initialValue, variableValues, subsequentPayloads)} _ normally_
141
143
(allowing parallelization).
142
144
- Let {errors} be the list of all _ field error_ raised while executing the
@@ -171,7 +173,9 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
171
173
- Let {mutationType} be the root Mutation type in {schema}.
172
174
- Assert: {mutationType} is an Object type.
173
175
- Let {selectionSet} be the top level Selection Set in {mutation}.
174
- - Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
176
+ - Let {groupedFieldSet} and {deferredGroupedFieldsList} be the result of
177
+ {CollectRootFields(queryType, selectionSet, variableValues)}.
178
+ - Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet,
175
179
mutationType, initialValue, variableValues, subsequentPayloads)} _ serially_ .
176
180
- Let {errors} be the list of all _ field error_ raised while executing the
177
181
selection set.
@@ -286,7 +290,7 @@ CreateSourceEventStream(subscription, schema, variableValues, initialValue):
286
290
- Let {subscriptionType} be the root Subscription type in {schema}.
287
291
- Assert: {subscriptionType} is an Object type.
288
292
- Let {selectionSet} be the top level Selection Set in {subscription}.
289
- - Let {groupedFieldSet} be the result of {CollectFields (subscriptionType,
293
+ - Let {groupedFieldSet} be the result of {CollectRootFields (subscriptionType,
290
294
selectionSet, variableValues)}.
291
295
- If {groupedFieldSet} does not have exactly one entry, raise a _ request error_ .
292
296
- Let {fields} be the value of the first entry in {groupedFieldSet}.
@@ -332,7 +336,9 @@ ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
332
336
- Let {subscriptionType} be the root Subscription type in {schema}.
333
337
- Assert: {subscriptionType} is an Object type.
334
338
- Let {selectionSet} be the top level Selection Set in {subscription}.
335
- - Let {data} be the result of running {ExecuteSelectionSet(selectionSet,
339
+ - Let {groupedFieldSet} be the result of {CollectRootFields(subscriptionType,
340
+ selectionSet, variableValues)}.
341
+ - Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet,
336
342
subscriptionType, initialValue, variableValues)} _ normally_ (allowing
337
343
parallelization).
338
344
- Let {errors} be the list of all _ field error_ raised while executing the
@@ -400,23 +406,20 @@ YieldSubsequentPayloads(initialResponse, subsequentPayloads):
400
406
{true}.
401
407
- Yield {subsequentResponse}
402
408
403
- ## Executing Selection Sets
409
+ ## Executing Grouped Field Sets
404
410
405
- To execute a selection set, the object value being evaluated and the object type
406
- need to be known, as well as whether it must be executed serially, or may be
407
- executed in parallel.
411
+ To execute a grouped field set, the object value being evaluated and the object
412
+ type need to be known, as well as whether it must be executed serially, or may
413
+ be executed in parallel.
408
414
409
- First, the selection set is turned into a grouped field set; then, each
410
- represented field in the grouped field set produces an entry into a response
411
- map.
415
+ Each represented field in the grouped field set produces an entry into a
416
+ response map.
412
417
413
- ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues, path ,
414
- subsequentPayloads, asyncRecord):
418
+ ExecuteGroupedFieldSet(groupedFieldSet, deferredGroupedFieldsList, objectType ,
419
+ objectValue, variableValues, path, subsequentPayloads, asyncRecord):
415
420
416
421
- If {path} is not provided, initialize it to an empty list.
417
422
- If {subsequentPayloads} is not provided, initialize it to the empty set.
418
- - Let {groupedFieldSet} and {deferredGroupedFieldsList} be the result of
419
- {CollectFields(objectType, selectionSet, variableValues, path, asyncRecord)}.
420
423
- Initialize {resultMap} to an empty ordered map.
421
424
- For each {groupedFieldSet} as {responseKey} and {fields}:
422
425
- Let {fieldName} be the name of the first entry in {fields}. Note: This value
@@ -651,8 +654,7 @@ response in a stable and predictable order.
651
654
CollectFields(objectType, selectionSet, variableValues, path, asyncRecord,
652
655
visitedFragments, deferredGroupedFieldsList):
653
656
654
- - If {visitedFragments} is not provided, initialize it to the empty set.
655
- - Initialize {groupedFields} to an empty ordered map of lists.
657
+ - Initialize {groupedFieldSet} to an empty ordered map of lists.
656
658
- If {deferredGroupedFieldsList} is not provided, initialize it to an empty
657
659
list.
658
660
- For each {selection} in {selectionSet}:
@@ -669,7 +671,7 @@ visitedFragments, deferredGroupedFieldsList):
669
671
- If {selection} is a {Field}:
670
672
- Let {responseKey} be the response key of {selection} (the alias if
671
673
defined, otherwise the field name).
672
- - Let {groupForResponseKey} be the list in {groupedFields } for
674
+ - Let {groupForResponseKey} be the list in {groupedFieldSet } for
673
675
{responseKey}; if no such list exists, create it as an empty list.
674
676
- Append {selection} to the {groupForResponseKey}.
675
677
- If {selection} is a {FragmentSpread}:
@@ -707,7 +709,7 @@ visitedFragments, deferredGroupedFieldsList):
707
709
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
708
710
- Let {responseKey} be the response key shared by all fields in
709
711
{fragmentGroup}.
710
- - Let {groupForResponseKey} be the list in {groupedFields } for
712
+ - Let {groupForResponseKey} be the list in {groupedFieldSet } for
711
713
{responseKey}; if no such list exists, create it as an empty list.
712
714
- Append all items in {fragmentGroup} to {groupForResponseKey}.
713
715
- If {selection} is an {InlineFragment}:
@@ -737,10 +739,10 @@ visitedFragments, deferredGroupedFieldsList):
737
739
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
738
740
- Let {responseKey} be the response key shared by all fields in
739
741
{fragmentGroup}.
740
- - Let {groupForResponseKey} be the list in {groupedFields } for
742
+ - Let {groupForResponseKey} be the list in {groupedFieldSet } for
741
743
{responseKey}; if no such list exists, create it as an empty list.
742
744
- Append all items in {fragmentGroup} to {groupForResponseKey}.
743
- - Return {groupedFields} and {deferredGroupedFieldsList }.
745
+ - Return {groupedFields}, {deferredGroupedFieldsList}, and {visitedFragments }.
744
746
745
747
Note: The steps in {CollectFields()} evaluating the ` @skip ` and ` @include `
746
748
directives may be applied in either order since they apply commutatively.
@@ -808,6 +810,39 @@ variableValues, parentRecord, subsequentPayloads):
808
810
- Set {dataExecution} on {deferredFragmentRecord}.
809
811
- Append {deferRecord} to {subsequentPayloads}.
810
812
813
+ ### Root Field Collection
814
+
815
+ Root field collection processes the operation's top-level selection set:
816
+
817
+ CollectRootFields(rootType, operationSelectionSet, variableValues):
818
+
819
+ - Initialize {visitedFragments} to the empty set.
820
+ - Let {groupedFieldSet} be the result of calling {CollectFields(rootType,
821
+ operationSelectionSet, variableValues, visitedFragments)}.
822
+ - Return {groupedFieldSet}.
823
+
824
+ ### Object Subfield Collection
825
+
826
+ Object subfield collection processes a field's sub-selection sets:
827
+
828
+ CollectSubfields(objectType, fields, variableValues):
829
+
830
+ - Initialize {visitedFragments} to the empty set.
831
+ - Initialize {groupedSubfieldSet} to an empty ordered map of lists.
832
+ - For each {field} in {fields}:
833
+ - Let {fieldSelectionSet} be the selection set of {field}.
834
+ - If {fieldSelectionSet} is null or empty, continue to the next field.
835
+ - Let {fieldGroupedFieldSet} be the result of calling
836
+ {CollectFields(objectType, fragmentSelectionSet, variableValues,
837
+ visitedFragments)}.
838
+ - For each {fieldGroup} in {fieldGroupedFieldSet}:
839
+ - Let {responseKey} be the response key shared by all fields in
840
+ {fragmentGroup}.
841
+ - Let {groupForResponseKey} be the list in {groupedFieldSet} for
842
+ {responseKey}; if no such list exists, create it as an empty list.
843
+ - Append all items in {fieldGroup} to {groupForResponseKey}.
844
+ - Return {groupedSubfieldSet}.
845
+
811
846
## Executing Fields
812
847
813
848
Each field requested in the grouped field set that is defined on the selected
@@ -1024,8 +1059,9 @@ subsequentPayloads, asyncRecord):
1024
1059
- Let {objectType} be {fieldType}.
1025
1060
- Otherwise if {fieldType} is an Interface or Union type.
1026
1061
- Let {objectType} be {ResolveAbstractType(fieldType, result)}.
1027
- - Let {subSelectionSet} be the result of calling {MergeSelectionSets(fields)}.
1028
- - Return the result of evaluating {ExecuteSelectionSet(subSelectionSet,
1062
+ - Let {groupedSubfieldSet} and {deferredGroupedFieldsList} be the result of
1063
+ calling {CollectSubfields(objectType, fields, variableValues)}.
1064
+ - Return the result of evaluating {ExecuteGroupedFieldSet(groupedSubfieldSet,
1029
1065
objectType, result, variableValues, path, subsequentPayloads, asyncRecord)}
1030
1066
_ normally_ (allowing for parallelization).
1031
1067
@@ -1090,17 +1126,9 @@ sub-selections.
1090
1126
}
1091
1127
```
1092
1128
1093
- After resolving the value for ` me ` , the selection sets are merged together so
1094
- ` firstName ` and ` lastName ` can be resolved for one value.
1095
-
1096
- MergeSelectionSets(fields):
1097
-
1098
- - Let {selectionSet} be an empty list.
1099
- - For each {field} in {fields}:
1100
- - Let {fieldSelectionSet} be the selection set of {field}.
1101
- - If {fieldSelectionSet} is null or empty, continue to the next field.
1102
- - Append all selections in {fieldSelectionSet} to {selectionSet}.
1103
- - Return {selectionSet}.
1129
+ After resolving the value for ` me ` , the selection sets are merged together by
1130
+ calling {CollectSubfields()} so ` firstName ` and ` lastName ` can be resolved for
1131
+ one value.
1104
1132
1105
1133
### Handling Field Errors
1106
1134
0 commit comments