@@ -86,10 +86,8 @@ CoerceVariableValues(schema, operation, variableValues):
86
86
- Let {coercedValues} be an empty unordered Map.
87
87
- Let {variablesDefinition} be the variables defined by {operation}.
88
88
- For each {variableDefinition} in {variablesDefinition}:
89
- - Let {variableName} be the name of {variableDefinition}.
90
- - Let {variableType} be the expected type of {variableDefinition}.
91
- - Assert: {IsInputType(variableType)} must be {true}.
92
- - Let {defaultValue} be the default value for {variableDefinition}.
89
+ - Let {variableName}, {variableType}, and {defaultValue} be the result of
90
+ {GetVariableSignature(variableDefinition)}.
93
91
- Let {hasValue} be {true} if {variableValues} provides a value for the name
94
92
{variableName}.
95
93
- Let {value} be the value provided in {variableValues} for the name
@@ -114,6 +112,14 @@ CoerceVariableValues(schema, operation, variableValues):
114
112
115
113
Note: This algorithm is very similar to {CoerceArgumentValues()}.
116
114
115
+ GetVariableSignature(variableDefinition):
116
+
117
+ - Let {variableName} be the name of {variableDefinition}.
118
+ - Let {variableType} be the expected type of {variableDefinition}.
119
+ - Assert: {IsInputType(variableType)} must be {true}.
120
+ - Let {defaultValue} be the default value for {variableDefinition}.
121
+ - Return {variableName}, {variableType}, and {defaultValue}.
122
+
117
123
## Executing Operations
118
124
119
125
The type system, as described in the "Type System" section of the spec, must
@@ -353,16 +359,16 @@ ExecuteGroupedFieldSet(groupedFieldSet, objectType, objectValue,
353
359
variableValues):
354
360
355
361
- Initialize {resultMap} to an empty ordered map.
356
- - For each {groupedFieldSet} as {responseKey} and {fields }:
357
- - Let {fieldName } be the name of the first entry in {fields}. Note: This value
358
- is unaffected if an alias is used .
359
- - Let {fragmentVariableValues } be the fragment-variables value of the first
360
- entry in {fields} .
362
+ - For each {groupedFieldSet} as {responseKey} and {fieldDetailsList }:
363
+ - Let {fieldDetails } be the first entry in {fieldDetailsList}.
364
+ - Let {field} be the corresponding entry on {fieldDetails} .
365
+ - Let {fieldName } be field name of {field}. Note: This value is unaffected if
366
+ an alias is used .
361
367
- Let {fieldType} be the return type defined for the field {fieldName} of
362
368
{objectType}.
363
369
- If {fieldType} is defined:
364
370
- Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType,
365
- fields , variableValues, fragmentVariableValues )}.
371
+ fieldDetailsList , variableValues)}.
366
372
- Set {responseValue} as the value for {responseKey} in {resultMap}.
367
373
- Return {resultMap}.
368
374
@@ -510,46 +516,56 @@ The depth-first-search order of the field groups produced by {CollectFields()}
510
516
is maintained through execution, ensuring that fields appear in the executed
511
517
response in a stable and predictable order.
512
518
513
- CollectFields(objectType, selectionSet, variableValues, visitedFragments ,
514
- localVariableValues ):
519
+ CollectFields(objectType, selectionSet, variableValues, fragmentVariables ,
520
+ visitedFragments ):
515
521
516
522
- If {visitedFragments} is not provided, initialize it to the empty set.
517
523
- Initialize {groupedFields} to an empty ordered map of lists.
518
524
- For each {selection} in {selectionSet}:
519
525
- If {selection} provides the directive ` @skip ` , let {skipDirective} be that
520
526
directive.
521
- - If {skipDirective}'s {if} argument is {true} or is a variable in
522
- {localVariableValues} or {variableValues} with the value {true}, continue
523
- with the next {selection} in {selectionSet}.
527
+ - Let {directiveValues} be the result of {GetDirectiveValues(skipDirective,
528
+ variableValues, fragmentVariables)}.
529
+ - If the entry for the {if} argument within {directiveValues} is {true},
530
+ continue with the next {selection} in {selectionSet}.
524
531
- If {selection} provides the directive ` @include ` , let {includeDirective} be
525
532
that directive.
526
- - If {includeDirective}'s {if} argument is not {true} and is not a variable
527
- in {localVariableValues} or {variableValues} with the value {true},
533
+ - Let {directiveValues} be the result of
534
+ {GetDirectiveValues(includeDirective, variableValues, fragmentVariables)}.
535
+ - If the entry for the {if} argument within {directiveValues} is not {true},
528
536
continue with the next {selection} in {selectionSet}.
529
537
- If {selection} is a {Field}:
530
538
- Let {responseKey} be the response key of {selection} (the alias if
531
539
defined, otherwise the field name).
532
540
- Let {groupForResponseKey} be the list in {groupedFields} for
533
541
{responseKey}; if no such list exists, create it as an empty list.
534
- - Append {selection} and {localVariableValues} to the {groupForResponseKey}.
542
+ - Let {fieldDetails} be a new unordered map containing {fragmentVariables}.
543
+ - Set the entry for {field} on {fieldDetails} to {selection}.
544
+ - Append {fieldDetails} to the {groupForResponseKey}.
535
545
- If {selection} is a {FragmentSpread}:
536
546
- Let {fragmentSpreadName} be the name of {selection}.
547
+ - If {fragmentSpreadName} is in {visitedFragments}, continue with the next
548
+ {selection} in {selectionSet}.
549
+ - Add {fragmentSpreadName} to {visitedFragments}.
537
550
- Let {fragment} be the Fragment in the current Document whose name is
538
551
{fragmentSpreadName}.
539
552
- If no such {fragment} exists, continue with the next {selection} in
540
553
{selectionSet}.
541
- - If {fragmentSpreadName} is in {visitedFragments}, continue with the next
542
- {selection} in {selectionSet}.
543
- - Add {fragmentSpreadName} to {visitedFragments}.
544
554
- Let {fragmentType} be the type condition on {fragment}.
545
555
- If {DoesFragmentTypeApply(objectType, fragmentType)} is {false}, continue
546
556
with the next {selection} in {selectionSet}.
547
- - Let {localVariableValues} be the result of calling
548
- {getArgumentValuesFromSpread(selection, fragmentDefinition,
549
- variableValues, localVariableValues)}.
557
+ - Let {variableDefinitions} be the variable definitions for {fragment}.
558
+ - Initialize {signatures} to an empty list.
559
+ - For each {variableDefinition} of {variableDefinitions}:
560
+ - Append the result of {GetVariableSignature(variableDefinition)} to
561
+ {signatures}.
562
+ - Let {values} be the result of {CoerceArgumentValues(fragment,
563
+ argumentDefinitions, variableValues, fragmentVariables)}.
564
+ - Let {newFragmentVariables} be an unordered map containing {signatures} and
565
+ {values}.
550
566
- Let {fragmentGroupedFieldSet} be the result of calling
551
567
{CollectFields(objectType, fragmentSelectionSet, variableValues,
552
- visitedFragments)}.
568
+ newFragmentVariables, visitedFragments)}.
553
569
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
554
570
- Let {responseKey} be the response key shared by all fields in
555
571
{fragmentGroup}.
@@ -564,7 +580,7 @@ localVariableValues):
564
580
- Let {fragmentSelectionSet} be the top-level selection set of {selection}.
565
581
- Let {fragmentGroupedFieldSet} be the result of calling
566
582
{CollectFields(objectType, fragmentSelectionSet, variableValues,
567
- visitedFragments)}.
583
+ fragmentVariables, visitedFragments)}.
568
584
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
569
585
- Let {responseKey} be the response key shared by all fields in
570
586
{fragmentGroup}.
@@ -585,32 +601,19 @@ DoesFragmentTypeApply(objectType, fragmentType):
585
601
- If {objectType} is a possible type of {fragmentType}, return {true}
586
602
otherwise return {false}.
587
603
588
- getArgumentValuesFromSpread(fragmentSpread, fragmentDefinition, variableValues,
589
- fragmentArgumentValues):
590
-
591
- - Let {coercedValues} be an empty unordered Map.
592
- - For each {variableDefinition} in {fragmentDefinition}:
593
- - Let {variableName} be the name of {variableDefinition}.
594
- - Let {variableType} be the type of {variableDefinition}.
595
- - Let {defaultValue} be the default value for {variableDefinition}.
596
- - Let {argumentNode} be the node provided in the fragment-spread for
597
- {variableName}
598
- - If {argumentNode} isn't present or is null
599
- - If {defaultValue} exists
600
- - Add an entry to {coercedValues} named {argumentName} with the value
601
- {defaultValue}.
602
- - If {variableType} is non-nullable raise a field-error
603
- - Let {hasValue} be {true} if {fragmentArgumentValues} or {variableValues}
604
- provides a value for the name {variableName}.
605
- - If {variableType} is non-nullable and {hasValue} is {false} raise a
606
- field-error
607
- - Add an entry to {coercedValues} named {argumentName} with the value found in
608
- {variableValues} or {fragmentArgumentValues}.
609
- - Return {coercedValues}.
610
-
611
604
Note: The steps in {CollectFields()} evaluating the ` @skip ` and ` @include `
612
605
directives may be applied in either order since they apply commutatively.
613
606
607
+ GetDirectiveValues(directive, variableValues, fragmentVariables):
608
+
609
+ - Let {directiveName} be the name of {directive}.
610
+ - Let {directiveDefinition} be the definition for {directiveName} within the
611
+ schema.
612
+ - Assert {directiveDefinition} is defined.
613
+ - Let {argumentDefinitions} be the arguments defined by {directiveDefinition}.
614
+ - Return the result of {CoerceArgumentValues(directiveDirective,
615
+ argumentDefinitions, variableValues, fragmentVariables)}.
616
+
614
617
## Executing Fields
615
618
616
619
Each field requested in the grouped field set that is defined on the selected
@@ -619,40 +622,37 @@ coerces any provided argument values, then resolves a value for the field, and
619
622
finally completes that value either by recursively executing another selection
620
623
set or coercing a scalar value.
621
624
622
- ExecuteField(objectType, objectValue, fieldType, fields, variableValues ,
623
- fragmentVariableValues ):
625
+ ExecuteField(objectType, objectValue, fieldType, fieldDetailsList ,
626
+ variableValues, fragmentVariables ):
624
627
625
- - Let {field} be the first entry in {fields}.
628
+ - Let {fieldDetails} be the first entry in {fieldDetailsList}.
629
+ - Let {field} and {fragmentVariables} be the corresponding entries on
630
+ {fieldDetails}.
626
631
- Let {fieldName} be the field name of {field}.
627
- - Let {argumentValues} be the result of {CoerceFieldArgumentValues(objectType,
628
- field, variableValues, fragmentVariableValues)}
632
+ - Let {argumentDefinitions} be the arguments defined by {objectType} for the
633
+ field named {fieldName}.
634
+ - Let {argumentValues} be the result of {CoerceArgumentValues(field,
635
+ argumentDefinitions, variableValues, fragmentVariables)}.
629
636
- Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName,
630
637
argumentValues)}.
631
- - Return the result of {CompleteValue(fieldType, fields, resolvedValue ,
632
- variableValues)}.
638
+ - Return the result of {CompleteValue(fieldType, fieldDetailsList ,
639
+ resolvedValue, variableValues)}.
633
640
634
- ### Coercing Field Arguments
641
+ ### Coercing Arguments
635
642
636
- Fields may include arguments which are provided to the underlying runtime in
637
- order to correctly produce a value. These arguments are defined by the field in
638
- the type system to have a specific input type.
643
+ Fields, directives, and fragment spreads may include arguments which are
644
+ provided to the underlying runtime in order to correctly produce a value. For
645
+ fields and directives, these arguments are defined by the field or directive in
646
+ the type system to have a specific input type; for fragment spreads, the
647
+ fragment definition within the document specifies the input type.
639
648
640
649
At each argument position in an operation may be a literal {Value}, or a
641
650
{Variable} to be provided at runtime.
642
651
643
- CoerceFieldArgumentValues(objectType, field, variableValues,
644
- fragmentVariableValues):
645
-
646
- - Let {argumentValues} be the argument values provided in {field}.
647
- - Let {fieldName} be the name of {field}.
648
- - Let {argumentDefinitions} be the arguments defined by {objectType} for the
649
- field named {fieldName}.
650
- - Return {CoerceArgumentValues(argumentDefinitions, argumentValues,
651
- variableValues, fragmentVariableValues)}
652
-
653
- CoerceArgumentValues(argumentDefinitions, argumentValues, variableValues,
654
- fragmentVariableValues):
652
+ CoerceArgumentValues(node, argumentDefinitions, variableValues,
653
+ fragmentVariables):
655
654
655
+ - Let {argumentValues} be the argument values provided in {node}.
656
656
- For each {argumentDefinition} in {argumentDefinitions}:
657
657
- Let {argumentName} be the name of {argumentDefinition}.
658
658
- Let {argumentType} be the expected type of {argumentDefinition}.
@@ -663,12 +663,12 @@ fragmentVariableValues):
663
663
{argumentName}.
664
664
- If {argumentValue} is a {Variable}:
665
665
- Let {variableName} be the name of {argumentValue}.
666
- - Let {hasValue} be {true} if {fragmentVariableValues} provides a value for
666
+ - Let {signatures} and {values} be the corresponding entries on
667
+ {fragmentVariables}.
668
+ - Let {scopedVariableValues} be {values} if an entry in {signatures} exists
669
+ for {variableName}; otherwise, let it be {variableValues}.
670
+ - Let {hasValue} be {true} if {scopedVariableValues} provides a value for
667
671
the name {variableName}.
668
- - Let {value} be the value provided in {fragmentVariableValues} for the name
669
- {variableName}.
670
- - Let {hasValue} be {true} if {variableValues} provides a value for the name
671
- {variableName}.
672
672
- Let {value} be the value provided in {variableValues} for the name
673
673
{variableName}.
674
674
- Otherwise, let {value} be {argumentValue}.
@@ -726,12 +726,12 @@ After resolving the value for a field, it is completed by ensuring it adheres to
726
726
the expected return type. If the return type is another Object type, then the
727
727
field execution process continues recursively.
728
728
729
- CompleteValue(fieldType, fields , result, variableValues):
729
+ CompleteValue(fieldType, fieldDetailsList , result, variableValues):
730
730
731
731
- If the {fieldType} is a Non-Null type:
732
732
- Let {innerType} be the inner type of {fieldType}.
733
733
- Let {completedResult} be the result of calling {CompleteValue(innerType,
734
- fields , result, variableValues)}.
734
+ fieldDetailsList , result, variableValues)}.
735
735
- If {completedResult} is {null}, raise a _ field error_ .
736
736
- Return {completedResult}.
737
737
- If {result} is {null} (or another internal value similar to {null} such as
@@ -740,8 +740,8 @@ CompleteValue(fieldType, fields, result, variableValues):
740
740
- If {result} is not a collection of values, raise a _ field error_ .
741
741
- Let {innerType} be the inner type of {fieldType}.
742
742
- Return a list where each list item is the result of calling
743
- {CompleteValue(innerType, fields , resultItem, variableValues)}, where
744
- {resultItem} is each item in {result}.
743
+ {CompleteValue(innerType, fieldDetailsList , resultItem, variableValues)},
744
+ where {resultItem} is each item in {result}.
745
745
- If {fieldType} is a Scalar or Enum type:
746
746
- Return the result of {CoerceResult(fieldType, result)}.
747
747
- If {fieldType} is an Object, Interface, or Union type:
@@ -750,7 +750,7 @@ CompleteValue(fieldType, fields, result, variableValues):
750
750
- Otherwise if {fieldType} is an Interface or Union type.
751
751
- Let {objectType} be {ResolveAbstractType(fieldType, result)}.
752
752
- Let {groupedFieldSet} be the result of calling {CollectSubfields(objectType,
753
- fields , variableValues)}.
753
+ fieldDetailsList , variableValues)}.
754
754
- Return the result of evaluating {ExecuteGroupedFieldSet(groupedFieldSet,
755
755
objectType, result, variableValues)} _ normally_ (allowing for
756
756
parallelization).
@@ -819,18 +819,20 @@ sub-selections.
819
819
After resolving the value for ` me ` , the selection sets are merged together so
820
820
` firstName ` and ` lastName ` can be resolved for one value.
821
821
822
- CollectSubfields(objectType, fields , variableValues):
822
+ CollectSubfields(objectType, fieldDetailsList , variableValues):
823
823
824
824
- Let {groupedFieldSet} be an empty map.
825
- - For each {field} in {fields}:
825
+ - For each {fieldDetails} in {fieldDetailsList}:
826
+ - Let {field} be the corresponding entry on {fieldDetails}.
826
827
- Let {fieldSelectionSet} be the selection set of {field}.
827
828
- If {fieldSelectionSet} is null or empty, continue to the next field.
829
+ - Let {fragmentVariables} be the corresponding entry on {fieldDetails}.
828
830
- Let {subGroupedFieldSet} be the result of {CollectFields(objectType,
829
- fieldSelectionSet, variableValues)}.
830
- - For each {subGroupedFieldSet} as {responseKey} and {subfields }:
831
+ fieldSelectionSet, variableValues, fragmentVariables )}.
832
+ - For each {subGroupedFieldSet} as {responseKey} and {subfieldDetailsList }:
831
833
- Let {groupForResponseKey} be the list in {groupedFieldSet} for
832
834
{responseKey}; if no such list exists, create it as an empty list.
833
- - Append all fields in {subfields } to {groupForResponseKey}.
835
+ - Append all fields in {subfieldDetailsList } to {groupForResponseKey}.
834
836
- Return {groupedFieldSet}.
835
837
836
838
### Handling Field Errors
0 commit comments