@@ -286,8 +286,9 @@ CreateSourceEventStream(subscription, schema, variableValues, initialValue):
286
286
selectionSet, variableValues)}.
287
287
- If {collectedFieldsMap} does not have exactly one entry, raise a _ request
288
288
error_ .
289
- - Let {fields} be the value of the first entry in {collectedFieldsMap}.
290
- - Let {fieldName} be the name of the first entry in {fields}. Note: This value
289
+ - Let {fieldInfo} be the value of the first entry in {collectedFieldsMap}.
290
+ - Let {field} be the value of the {field} property in {fieldInfo}.
291
+ - Let {fieldName} be the name of the first entry in {fields}' {field} property. Note: This value
291
292
is unaffected if an alias is used.
292
293
- Let {field} be the first entry in {fields}.
293
294
- Let {argumentValues} be the result of {CoerceArgumentValues(subscriptionType,
@@ -446,7 +447,8 @@ The depth-first-search order of the _field set_ produced by {CollectFields()} is
446
447
maintained through execution, ensuring that fields appear in the executed
447
448
response in a stable and predictable order.
448
449
449
- CollectFields(objectType, selectionSet, variableValues, visitedFragments):
450
+ CollectFields(objectType, selectionSet, variableValues, visitedFragments,
451
+ fragmentVariables):
450
452
451
453
- If {visitedFragments} is not provided, initialize it to the empty set.
452
454
- Initialize {collectedFieldsMap} to an empty ordered map of ordered sets.
@@ -464,10 +466,12 @@ CollectFields(objectType, selectionSet, variableValues, visitedFragments):
464
466
- If {selection} is a {Field}:
465
467
- Let {responseName} be the _ response name_ of {selection} (the alias if
466
468
defined, otherwise the field name).
467
- - Let {fieldsForResponseName} be the _ field set _ value in
469
+ - Let {fieldsForResponseName} be the _ field map _ value in
468
470
{collectedFieldsMap} for the key {responseName}; otherwise create the
469
471
entry with an empty ordered set.
470
- - Add {selection} to the {fieldsForResponseName}.
472
+ - Let {fieldDetails} be a new unordered map containing {fragmentVariables}.
473
+ - Set the entry for {field} on {fieldDetails} to {selection}.
474
+ - Add {fieldDetails} to the {fieldsForResponseName}.
471
475
- If {selection} is a {FragmentSpread}:
472
476
- Let {fragmentSpreadName} be the name of {selection}.
473
477
- If {fragmentSpreadName} is in {visitedFragments}, continue with the next
@@ -480,10 +484,19 @@ CollectFields(objectType, selectionSet, variableValues, visitedFragments):
480
484
- Let {fragmentType} be the type condition on {fragment}.
481
485
- If {DoesFragmentTypeApply(objectType, fragmentType)} is {false}, continue
482
486
with the next {selection} in {selectionSet}.
487
+ - Let {variableDefinitions} be the variable definitions for {fragment}.
488
+ - Initialize {signatures} to an empty list.
489
+ - For each {variableDefinition} of {variableDefinitions}:
490
+ - Append the result of {GetVariableSignature(variableDefinition)} to
491
+ {signatures}.
492
+ - Let {values} be the result of {CoerceArgumentValues(fragment,
493
+ argumentDefinitions, variableValues, fragmentVariables)}.
494
+ - Let {newFragmentVariables} be an unordered map containing {signatures} and
495
+ {values}.
483
496
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
484
497
- Let {fragmentCollectedFieldMap} be the result of calling
485
498
{CollectFields(objectType, fragmentSelectionSet, variableValues,
486
- visitedFragments)}.
499
+ visitedFragments, newFragmentVariables )}.
487
500
- For each {responseName} and {fragmentFields} in
488
501
{fragmentCollectedFieldMap}:
489
502
- Let {fieldsForResponseName} be the _ field set_ value in
@@ -498,7 +511,7 @@ CollectFields(objectType, selectionSet, variableValues, visitedFragments):
498
511
- Let {fragmentSelectionSet} be the top-level selection set of {selection}.
499
512
- Let {fragmentCollectedFieldMap} be the result of calling
500
513
{CollectFields(objectType, fragmentSelectionSet, variableValues,
501
- visitedFragments)}.
514
+ visitedFragments, fragmentVariables )}.
502
515
- For each {responseName} and {fragmentFields} in
503
516
{fragmentCollectedFieldMap}:
504
517
- Let {fieldsForResponseName} be the _ field set_ value in
@@ -562,11 +575,11 @@ CollectSubfields(objectType, fields, variableValues):
562
575
- If {fieldSelectionSet} is null or empty, continue to the next field.
563
576
- Let {fieldCollectedFieldMap} be the result of {CollectFields(objectType,
564
577
fieldSelectionSet, variableValues)}.
565
- - For each {responseName} and {subfields } in {fieldCollectedFieldMap}:
578
+ - For each {responseName} and {subfieldInfos } in {fieldCollectedFieldMap}:
566
579
- Let {fieldsForResponseName} be the _ field set_ value in
567
580
{collectedFieldsMap} for the key {responseName}; otherwise create the
568
581
entry with an empty ordered set.
569
- - Add each fields from {subfields} to {fieldsForResponseName}.
582
+ - Add each fieldInfo from {subfields} to {fieldsForResponseName}.
570
583
- Return {collectedFieldsMap}.
571
584
572
585
Note: All the {fields} passed to {CollectSubfields()} share the same _ response
@@ -585,11 +598,12 @@ ExecuteCollectedFields(collectedFieldsMap, objectType, objectValue,
585
598
variableValues):
586
599
587
600
- Initialize {resultMap} to an empty ordered map.
588
- - For each {responseName} and {fields} in {collectedFieldsMap}:
601
+ - For each {responseName} and {fieldInfos} in {collectedFieldsMap}:
602
+ - Let {fieldInfo} be the first entry in {fieldInfos}.
603
+ - Let {field} be the field property of {fieldInfo}.
589
604
- Let {fieldName} be the name of the first entry in {fields}. Note: This value
590
605
is unaffected if an alias is used.
591
- - Let {fragmentVariableValues} be the fragment-variables value of the first
592
- entry in {fields}.
606
+ - Let {fragmentVariableValues} be the fragmentVariables property of {fieldInfo}.
593
607
- Let {fieldType} be the return type defined for the field {fieldName} of
594
608
{objectType}.
595
609
- If {fieldType} is defined:
@@ -720,134 +734,6 @@ A correct executor must generate the following result for that _selection set_:
720
734
}
721
735
```
722
736
723
- ### Field Collection
724
-
725
- Before execution, the _ selection set_ is converted to a grouped field set by
726
- calling {CollectFields()}. Each entry in the grouped field set is a list of
727
- fields that share a response key (the alias if defined, otherwise the field
728
- name). This ensures all fields with the same response key (including those in
729
- referenced fragments) are executed at the same time.
730
-
731
- As an example, collecting the fields of this selection set would collect two
732
- instances of the field ` a ` and one of field ` b ` :
733
-
734
- ``` graphql example
735
- {
736
- a {
737
- subfield1
738
- }
739
- ... ExampleFragment
740
- }
741
-
742
- fragment ExampleFragment on Query {
743
- a {
744
- subfield2
745
- }
746
- b
747
- }
748
- ```
749
-
750
- The depth-first-search order of the field groups produced by {CollectFields()}
751
- is maintained through execution, ensuring that fields appear in the executed
752
- response in a stable and predictable order.
753
-
754
- CollectFields(objectType, selectionSet, variableValues, visitedFragments,
755
- fragmentVariables):
756
-
757
- - If {visitedFragments} is not provided, initialize it to the empty set.
758
- - Initialize {groupedFields} to an empty ordered map of lists.
759
- - For each {selection} in {selectionSet}:
760
- - If {selection} provides the directive ` @skip ` , let {skipDirective} be that
761
- directive.
762
- - Let {directiveValues} be the result of {GetDirectiveValues(skipDirective,
763
- variableValues, fragmentVariables)}.
764
- - If the entry for the {if} argument within {directiveValues} is {true},
765
- continue with the next {selection} in {selectionSet}.
766
- - If {selection} provides the directive ` @include ` , let {includeDirective} be
767
- that directive.
768
- - Let {directiveValues} be the result of
769
- {GetDirectiveValues(includeDirective, variableValues, fragmentVariables)}.
770
- - If the entry for the {if} argument within {directiveValues} is not {true},
771
- - If {selection} is a {Field}:
772
- - Let {responseKey} be the response key of {selection} (the alias if
773
- defined, otherwise the field name).
774
- - Let {groupForResponseKey} be the list in {groupedFields} for
775
- {responseKey}; if no such list exists, create it as an empty list.
776
- - Let {fieldDetails} be a new unordered map containing {fragmentVariables}.
777
- - Set the entry for {field} on {fieldDetails} to {selection}.
778
- - Append {fieldDetails} to the {groupForResponseKey}.
779
- - If {selection} is a {FragmentSpread}:
780
- - Let {fragmentSpreadName} be the name of {selection}.
781
- - If {fragmentSpreadName} is in {visitedFragments}, continue with the next
782
- {selection} in {selectionSet}.
783
- - Add {fragmentSpreadName} to {visitedFragments}.
784
- - Let {fragment} be the Fragment in the current Document whose name is
785
- {fragmentSpreadName}.
786
- - If no such {fragment} exists, continue with the next {selection} in
787
- {selectionSet}.
788
- - Let {fragmentType} be the type condition on {fragment}.
789
- - If {DoesFragmentTypeApply(objectType, fragmentType)} is {false}, continue
790
- with the next {selection} in {selectionSet}.
791
- - Let {variableDefinitions} be the variable definitions for {fragment}.
792
- - Initialize {signatures} to an empty list.
793
- - For each {variableDefinition} of {variableDefinitions}:
794
- - Append the result of {GetVariableSignature(variableDefinition)} to
795
- {signatures}.
796
- - Let {values} be the result of {CoerceArgumentValues(fragment,
797
- argumentDefinitions, variableValues, fragmentVariables)}.
798
- - Let {newFragmentVariables} be an unordered map containing {signatures} and
799
- {values}.
800
- - Let {fragmentGroupedFieldSet} be the result of calling
801
- {CollectFields(objectType, fragmentSelectionSet, variableValues,
802
- visitedFragments, newFragmentVariables)}.
803
- - For each {fragmentGroup} in {fragmentGroupedFieldSet}:
804
- - Let {responseKey} be the response key shared by all fields in
805
- {fragmentGroup}.
806
- - Let {groupForResponseKey} be the list in {groupedFields} for
807
- {responseKey}; if no such list exists, create it as an empty list.
808
- - Append all items in {fragmentGroup} to {groupForResponseKey}.
809
- - If {selection} is an {InlineFragment}:
810
- - Let {fragmentType} be the type condition on {selection}.
811
- - If {fragmentType} is not {null} and {DoesFragmentTypeApply(objectType,
812
- fragmentType)} is {false}, continue with the next {selection} in
813
- {selectionSet}.
814
- - Let {fragmentSelectionSet} be the top-level selection set of {selection}.
815
- - Let {fragmentGroupedFieldSet} be the result of calling
816
- {CollectFields(objectType, fragmentSelectionSet, variableValues,
817
- visitedFragments, fragmentVariables)}.
818
- - For each {fragmentGroup} in {fragmentGroupedFieldSet}:
819
- - Let {responseKey} be the response key shared by all fields in
820
- {fragmentGroup}.
821
- - Let {groupForResponseKey} be the list in {groupedFields} for
822
- {responseKey}; if no such list exists, create it as an empty list.
823
- - Append all items in {fragmentGroup} to {groupForResponseKey}.
824
- - Return {groupedFields}.
825
-
826
- DoesFragmentTypeApply(objectType, fragmentType):
827
-
828
- - If {fragmentType} is an Object Type:
829
- - If {objectType} and {fragmentType} are the same type, return {true},
830
- otherwise return {false}.
831
- - If {fragmentType} is an Interface Type:
832
- - If {objectType} is an implementation of {fragmentType}, return {true}
833
- otherwise return {false}.
834
- - If {fragmentType} is a Union:
835
- - If {objectType} is a possible type of {fragmentType}, return {true}
836
- otherwise return {false}.
837
-
838
- Note: The steps in {CollectFields()} evaluating the ` @skip ` and ` @include `
839
- directives may be applied in either order since they apply commutatively.
840
-
841
- GetDirectiveValues(directive, variableValues, fragmentVariables):
842
-
843
- - Let {directiveName} be the name of {directive}.
844
- - Let {directiveDefinition} be the definition for {directiveName} within the
845
- schema.
846
- - Assert {directiveDefinition} is defined.
847
- - Let {argumentDefinitions} be the arguments defined by {directiveDefinition}.
848
- - Return the result of {CoerceArgumentValues(directiveDefinition,
849
- argumentDefinitions, variableValues, fragmentVariables)}.
850
-
851
737
## Executing Fields
852
738
853
739
Each entry in a result map is the result of executing a field on an object type
@@ -856,19 +742,16 @@ first coerces any provided argument values, then resolves a value for the field,
856
742
and finally completes that value either by recursively executing another
857
743
selection set or coercing a scalar value.
858
744
859
- ### TODO: this needs updating
860
-
861
- ExecuteField(objectType, objectValue, fieldType, fields, variableValues,
862
- fragmentVariableValues):
745
+ ExecuteField(objectType, objectValue, fieldType, fieldDetailsList, variableValues,
746
+ fragmentVariables):
863
747
864
- - Let {field} be the first entry in {fields}.
748
+ - Let {fieldDetails} be the first entry in {fieldDetailsList}.
749
+ - Let {field} and {fragmentVariables} be the corresponding entries on {fieldDetails}.
865
750
- Let {fieldName} be the field name of {field}.
866
- - Let {argumentValues} be the result of {CoerceFieldArgumentValues(objectType,
867
- field, variableValues, fragmentVariableValues)}
868
- - Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName,
869
- argumentValues)}.
870
- - Return the result of {CompleteValue(fieldType, fields, resolvedValue,
871
- variableValues)}.
751
+ - Let {argumentDefinitions} be the arguments defined by {objectType} for the field named {fieldName}.
752
+ - Let {argumentValues} be the result of {CoerceArgumentValues(field, argumentDefinitions, variableValues, fragmentVariables)}.
753
+ - Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName, argumentValues)}.
754
+ Return the result of {CompleteValue(fieldType, fieldDetailsList, resolvedValue, variableValues)}.
872
755
873
756
### Coercing Arguments
874
757
0 commit comments