@@ -131,17 +131,18 @@ ExecuteQuery(query, schema, variableValues, initialValue):
131
131
- Let {queryType} be the root Query type in {schema}.
132
132
- Assert: {queryType} is an Object type.
133
133
- Let {selectionSet} be the top level Selection Set in {query}.
134
- - Let {data}, {pendings } be the result of running
134
+ - Let {data}, {defers}, {streams } be the result of running
135
135
{ExecuteSelectionSet(selectionSet, queryType, initialValue, variableValues)}
136
136
_ normally_ (allowing parallelization).
137
137
- Let {errors} be the list of all _ field error_ raised while executing the
138
138
selection set.
139
- - If {pendings } is empty:
139
+ - If {defers } is an empty map and {streams} is an empty list :
140
140
- Return an unordered map containing {data} and {errors}.
141
141
- Else:
142
- - Return {IncrementalStream(data, errors, pendings, variableValues)}.
142
+ - Return {IncrementalEventStream(data, errors, defers, streams,
143
+ variableValues)}.
143
144
144
- IncrementalStream (data, errors, pendings , variableValues):
145
+ IncrementalEventStream (data, errors, defers, streams , variableValues):
145
146
146
147
- Let {responseStream} be a new event stream {responseStream}.
147
148
- Let {hasNext} be {true}.
@@ -207,17 +208,18 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
207
208
- Let {mutationType} be the root Mutation type in {schema}.
208
209
- Assert: {mutationType} is an Object type.
209
210
- Let {selectionSet} be the top level Selection Set in {mutation}.
210
- - Let {data}, {pendings } be the result of running
211
+ - Let {data}, {defers} and {streams } be the result of running
211
212
{ExecuteSelectionSet(selectionSet, mutationType, initialValue,
212
213
variableValues)} _ serially_ .
213
214
- Let {errors} be the list of all _ field error_ raised while executing the
214
215
selection set.
215
- - If {pendings } is empty:
216
+ - If {defers } is an empty map and {streams} is an empty list :
216
217
- Return an unordered map containing {data} and {errors}.
217
218
- Else:
218
219
- Note: this places the defers after _ all_ the mutations. This may not be
219
220
desired; we should discuss.
220
- - Return {IncrementalStream(data, errors, pendings, variableValues)}.
221
+ - Return {IncrementalEventStream(data, errors, defers, streams,
222
+ variableValues)}.
221
223
222
224
### Subscription
223
225
@@ -366,17 +368,18 @@ ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
366
368
- Let {subscriptionType} be the root Subscription type in {schema}.
367
369
- Assert: {subscriptionType} is an Object type.
368
370
- Let {selectionSet} be the top level Selection Set in {subscription}.
369
- - Let {data}, {pendings } be the result of running
371
+ - Let {data}, {defers} and {streams } be the result of running
370
372
{ExecuteSelectionSet(selectionSet, subscriptionType, initialValue,
371
373
variableValues)} _ normally_ (allowing parallelization).
372
374
- Let {errors} be the list of all _ field error_ raised while executing the
373
375
selection set.
374
- - If {pendings } is empty:
376
+ - If {defers } is an empty map and {streams} is an empty list :
375
377
- Return an unordered map containing {data} and {errors}.
376
378
- Else:
377
379
- Note: this places the defers after _ all_ the mutations. This may not be
378
380
desired; we should discuss.
379
- - Return {IncrementalStream(data, errors, pendings, variableValues)}.
381
+ - Return {IncrementalEventStream(data, errors, defers, streams,
382
+ variableValues)}.
380
383
381
384
Note: The {ExecuteSubscriptionEvent()} algorithm is intentionally similar to
382
385
{ExecuteQuery()} since this is how each event result is produced.
@@ -402,26 +405,35 @@ First, the selection set is turned into a grouped field set; then, each
402
405
represented field in the grouped field set produces an entry into a response
403
406
map.
404
407
405
- ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues):
408
+ ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues,
409
+ parentPath):
406
410
411
+ - If {parentPath} is not provided, initialize it to an empty list.
407
412
- Let {groupedFieldSet} be the result of {CollectFields(objectType,
408
- selectionSet, variableValues)}.
413
+ selectionSet, variableValues, parentPath )}.
409
414
- Initialize {resultMap} to an empty ordered map.
410
- - Let {deferred } be an empty list .
415
+ - Let {defers } be an empty unordered map .
411
416
- Let {streams} be an empty list.
412
417
- For each {groupedFieldSet} as {responseKey} and {fieldDetails}:
413
418
- Let {fieldDetail} be the first entry in {fieldDetails}.
414
419
- Let {field} be the value for the key {field} in {fieldDetail}.
420
+ - Let {path} be the value for the key {path} in {fieldDetail}.
415
421
- Let {fieldName} be the name of {field}. Note: This value is unaffected if an
416
422
alias is used.
417
423
- Let {fieldType} be the return type defined for the field {fieldName} of
418
424
{objectType}.
419
425
- If {fieldType} is defined:
420
426
- If every entry in {fieldDetails} has {isDeferred} set to {true}:
421
- - Add {fieldDetails} to {deferred}.
427
+ - Let {deferredGroupForPath} be the list in {defers} for {path}; if no
428
+ such list exists, create it as an empty list.
429
+ - Append {fieldDetails} to {deferredGroupForPath}.
422
430
- Else:
423
- - Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType,
424
- fieldDetails, variableValues)}.
431
+ - Let {responseValue}, {childDefers}, {childStreams} be
432
+ {ExecuteField(objectType, objectValue, fieldType, fieldDetails,
433
+ variableValues, path)}.
434
+ - Add the entries of {childDefers} into {defers}. Note: {childDefers} and
435
+ {defers} will never have keys in common.
436
+ - For each entry {stream} in {childStreams}, append {stream} to {streams}.
425
437
- If {responseValue} is not null and {fieldType} is a list type and
426
438
{field} provides the directive ` @stream ` , let {streamDirective} be that
427
439
directive. If {streamDirective}'s {if} argument is not {false} and is
@@ -438,15 +450,12 @@ ExecuteSelectionSet(selectionSet, objectType, objectValue, variableValues):
438
450
{responesValue}, and {remainingValues} be the remainder.
439
451
- Set {initialValues} as the value for {responseKey} in {resultMap}.
440
452
- If there are (or may be) values in {remainingValues}:
441
- - TODO: add {remainingValues} to {streams} via some mechanism...
453
+ - Let {streamDetails} be an unordered map containing {path},
454
+ {remainingValues} and {fieldDetails}.
455
+ - Append {streamDetails} to {streams}.
442
456
- Else:
443
457
- Set {responseValue} as the value for {responseKey} in {resultMap}.
444
- - Let {pendings} be an empty list.
445
- - If {deferred} is not empty:
446
- - Add a single entry to {pendings}.
447
- - For each {stream} in {streams}:
448
- - Add {something} to {pendings}.
449
- - Return {resultMap} and {pendings}.
458
+ - Return {resultMap}, {defers} and {streams}.
450
459
451
460
Note: {resultMap} is ordered by which fields appear first in the operation. This
452
461
is explained in greater detail in the Field Collection section below.
@@ -591,8 +600,9 @@ is maintained through execution, ensuring that fields appear in the executed
591
600
response in a stable and predictable order.
592
601
593
602
CollectFields(objectType, selectionSet, variableValues, isDeferred,
594
- visitedFragments):
603
+ visitedFragments, parentPath ):
595
604
605
+ - If {parentPath} is not provided, initialize it to an empty list.
596
606
- If {isDeferred} is not provided, initialize it to {false}.
597
607
- If {visitedFragments} is not provided, initialize it to the empty set.
598
608
- Initialize {groupedFields} to an empty ordered map of lists.
@@ -611,9 +621,11 @@ visitedFragments):
611
621
- Let {field} be {selection}.
612
622
- Let {responseKey} be the response key of {field} (the alias if defined,
613
623
otherwise the field name).
624
+ - Let {path} be a copy of {parentPath} with {responseKey} appended.
614
625
- Let {groupForResponseKey} be the list in {groupedFields} for
615
626
{responseKey}; if no such list exists, create it as an empty list.
616
- - Let {fieldDetail} be an unordered map containing {field} and {isDeferred}.
627
+ - Let {fieldDetail} be an unordered map containing {field}, {path} and
628
+ {isDeferred}.
617
629
- Append {fieldDetail} to the {groupForResponseKey}.
618
630
- If {selection} is a {FragmentSpread}:
619
631
- Let {fragmentSpreadName} be the name of {selection}.
@@ -636,7 +648,7 @@ visitedFragments):
636
648
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
637
649
- Let {fragmentGroupedFieldSet} be the result of calling
638
650
{CollectFields(objectType, fragmentSelectionSet, variableValues,
639
- fragmentIsDeferred, visitedFragments)}.
651
+ fragmentIsDeferred, visitedFragments, parentPath )}.
640
652
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
641
653
- Let {responseKey} be the response key shared by all fields in
642
654
{fragmentGroup}.
@@ -657,7 +669,7 @@ visitedFragments):
657
669
- Let {fragmentSelectionSet} be the top-level selection set of {selection}.
658
670
- Let {fragmentGroupedFieldSet} be the result of calling
659
671
{CollectFields(objectType, fragmentSelectionSet, variableValues,
660
- fragmentIsDeferred, visitedFragments)}.
672
+ fragmentIsDeferred, visitedFragments, parentPath )}.
661
673
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
662
674
- Let {responseKey} be the response key shared by all fields in
663
675
{fragmentGroup}.
@@ -689,16 +701,17 @@ coerces any provided argument values, then resolves a value for the field, and
689
701
finally completes that value either by recursively executing another selection
690
702
set or coercing a scalar value.
691
703
692
- ExecuteField(objectType, objectValue, fieldType, fields, variableValues):
704
+ ExecuteField(objectType, objectValue, fieldType, fields, variableValues, path ):
693
705
694
706
- Let {field} be the first entry in {fields}.
695
707
- Let {fieldName} be the field name of {field}.
696
708
- Let {argumentValues} be the result of {CoerceArgumentValues(objectType, field,
697
709
variableValues)}
698
710
- Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName,
699
711
argumentValues)}.
700
- - Return the result of {CompleteValue(fieldType, fields, resolvedValue,
701
- variableValues)}.
712
+ - Let {responseValue}, {defers} and {streams} be the result of
713
+ {CompleteValue(fieldType, fields, resolvedValue, variableValues, path)}.
714
+ - Return {responseValue}, {defers} and {streams}.
702
715
703
716
### Coercing Field Arguments
704
717
@@ -785,34 +798,51 @@ After resolving the value for a field, it is completed by ensuring it adheres to
785
798
the expected return type. If the return type is another Object type, then the
786
799
field execution process continues recursively.
787
800
788
- CompleteValue(fieldType, fields, result, variableValues):
801
+ CompleteValue(fieldType, fields, result, variableValues, path ):
789
802
790
- - TODO: overhaul for incremental!
791
803
- If the {fieldType} is a Non-Null type:
792
804
- Let {innerType} be the inner type of {fieldType}.
793
- - Let {completedResult} be the result of calling {CompleteValue(innerType,
794
- fields, result, variableValues)}.
805
+ - Let {completedResult}, {defers} and {streams} be the result of calling
806
+ {CompleteValue(innerType, fields, result, variableValues, path )}.
795
807
- If {completedResult} is {null}, raise a _ field error_ .
796
- - Return {completedResult}.
808
+ - Return {completedResult}, {defers} and {streams} .
797
809
- If {result} is {null} (or another internal value similar to {null} such as
798
- {undefined}), return {null}.
810
+ {undefined}):
811
+ - Let {completedResult} be {null}.
812
+ - Let {defers} be an empty unordered map.
813
+ - Let {streams} be an empty list.
814
+ - Return {completedResult}, {defers} and {streams}.
799
815
- If {fieldType} is a List type:
800
816
- If {result} is not a collection of values, raise a _ field error_ .
801
817
- Let {innerType} be the inner type of {fieldType}.
802
- - Return a list where each list item is the result of calling
803
- {CompleteValue(innerType, fields, resultItem, variableValues)}, where
804
- {resultItem} is each item in {result}.
818
+ - Let {defers} be an empty unordered map.
819
+ - Let {streams} be an empty list.
820
+ - Let {completedResult} be an empty list.
821
+ - For each entry {resultItem} at zero-based index {resultIndex} in {result}:
822
+ - Let {listItemPath} be a copy of {path} with {resultIndex} appended.
823
+ - Let {completedItemResult}, {childDefers} and {childStreams} be the result
824
+ of calling {CompleteValue(innerType, fields, resultItem, variableValues,
825
+ listItemPath)}.
826
+ - Add the entries of {childDefers} into {defers}. Note: {childDefers} and
827
+ {defers} will never have keys in common.
828
+ - For each entry {stream} in {childStreams}, append {stream} to {streams}.
829
+ - Append {completedItemResult} to {completedResult}.
830
+ - Return {completedResult}, {defers} and {streams}.
805
831
- If {fieldType} is a Scalar or Enum type:
806
- - Return the result of {CoerceResult(fieldType, result)}.
832
+ - Let {completedResult} be the result of {CoerceResult(fieldType, result)}.
833
+ - Let {defers} be an empty unordered map.
834
+ - Let {streams} be an empty list.
835
+ - Return {completedResult}, {defers} and {streams}.
807
836
- If {fieldType} is an Object, Interface, or Union type:
808
837
- If {fieldType} is an Object type.
809
838
- Let {objectType} be {fieldType}.
810
839
- Otherwise if {fieldType} is an Interface or Union type.
811
840
- Let {objectType} be {ResolveAbstractType(fieldType, result)}.
812
841
- Let {subSelectionSet} be the result of calling {MergeSelectionSets(fields)}.
813
- - Return the result of evaluating {ExecuteSelectionSet(subSelectionSet,
814
- objectType, result, variableValues)} _ normally_ (allowing for
815
- parallelization).
842
+ - Let {completedResult}, {defers} and {streams} be the result of evaluating
843
+ {ExecuteSelectionSet(subSelectionSet, objectType, result, variableValues,
844
+ path)} _ normally_ (allowing for parallelization).
845
+ - Return {completedResult}, {defers} and {streams}.
816
846
817
847
** Coercing Results**
818
848
0 commit comments