Skip to content

Commit af77053

Browse files
committed
update CollectFields algorithm
1 parent c06323a commit af77053

File tree

1 file changed

+135
-41
lines changed

1 file changed

+135
-41
lines changed

spec/Section 6 -- Execution.md

Lines changed: 135 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -739,10 +739,10 @@ Information about all fields sharing a response key are stored within Field
739739
Group records, structures containing:
740740

741741
- {parentType}: the type of the parent object for this field.
742+
- {fieldName}: the name of this field.
742743
- {fields}: a map of lists of collected field nodes, indexed by the Defer
743744
Details record corresponding to the originating enclosing deferred fragment,
744-
or {undefined} if the field is not contained by a deferred fragment.
745-
- {fieldDef}: the field definition for this field.
745+
or by {undefined} if the field is not contained by a deferred fragment.
746746
- {streamDetails}: information derived from any `@stream` directive on this
747747
field.
748748
- {priority}: the overall priority for this field group, equivalent to the
@@ -767,20 +767,18 @@ fragment ExampleFragment on Query {
767767
subfield2
768768
}
769769
b
770-
}
770+
}run
771771
```
772772

773773
The depth-first-search order of the field groups produced by {CollectFields()}
774774
is maintained through execution, ensuring that fields appear in the executed
775775
response in a stable and predictable order.
776776

777777
CollectFields(objectType, selectionSet, variableValues, visitedFragments,
778-
deferredGroupedFieldsList):
778+
priority, parentFieldGroup, deferredFragment):
779779

780-
- If {visitedFragments} is not provided, initialize it to the empty set.
781-
- Initialize {groupedFields} to an empty ordered map of lists.
782-
- If {deferredGroupedFieldsList} is not provided, initialize it to an empty
783-
list.
780+
- Initialize {groupedFieldSet} to an empty ordered map of Field Group records.
781+
- Initialize {deferredFragments} to an empty map of Defer Details records.
784782
- For each {selection} in {selectionSet}:
785783
- If {selection} provides the directive `@skip`, let {skipDirective} be that
786784
directive.
@@ -795,9 +793,30 @@ deferredGroupedFieldsList):
795793
- If {selection} is a {Field}:
796794
- Let {responseKey} be the response key of {selection} (the alias if
797795
defined, otherwise the field name).
798-
- Let {groupForResponseKey} be the list in {groupedFields} for
799-
{responseKey}; if no such list exists, create it as an empty list.
800-
- Append {selection} to the {groupForResponseKey}.
796+
- Let {groupForResponseKey} be the entry in in {groupedFieldSet} for
797+
{responseKey}.
798+
- If {groupForResponseKey} is {undefined}:
799+
- Let {fieldName} be the name of {selection}.
800+
- Initialize {fields} to an empty map of lists of collected field nodes,
801+
indexed by originating Defer Details record, or by {undefined}.
802+
- Let {listForDeferredFragment} be a list containing {selection}.
803+
- Set the entry for {deferredFragment} in {fields} to
804+
{listForDeferredFragment}.
805+
- If {selection} provides the directive `@stream` and its {if} argument is
806+
not {false} and is not a variable in {variableValues} with the value
807+
{false}, let {streamDirective} be that directive.
808+
- Let {groupForResponseKey} be a new Field Group record created from
809+
{runtimeType}, {fieldName}, {fields}, {streamDetails}, {priority}, and
810+
{parentFieldGroup}.
811+
- Otherwise:
812+
- Let {fields} be the corresponding entry on {groupForResponseKey}.
813+
- Let {listForDeferredFragment} be the list in {fields} for
814+
{deferredFragment}; if no such list exists, create it as an empty list.
815+
- Append {selection} to {listForDeferredFragment}.
816+
- Let {fieldGroupPriority} be the value of the {priority} entry on
817+
{fieldGroup}.
818+
- If {priority} is less than {fieldGroupPriority}, update the {priority}
819+
entry on {fieldGroup} to {priority}.
801820
- If {selection} is a {FragmentSpread}:
802821
- Let {fragmentSpreadName} be the name of {selection}.
803822
- If {fragmentSpreadName} provides the directive `@defer` and its {if}
@@ -818,24 +837,61 @@ deferredGroupedFieldsList):
818837
- If {DoesFragmentTypeApply(objectType, fragmentType)} is false, continue
819838
with the next {selection} in {selectionSet}.
820839
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
840+
- Let {maybeNewDefer} be equal to {deferDirective}.
841+
- Let {maybeIncreasedPriority} be equal to {priority}.
821842
- If {deferDirective} is defined:
843+
- If {parentFieldGroup} is {undefined}, set {maybeIncreasedPriority} to 1.
844+
- Otherwise:
845+
- Let {parentFieldGroupPriority} be the value of the {priority} entry on
846+
{parentFieldGroup}.
847+
- If {maybeIncreasedPriority} is equal to {parentFieldGroupPriority},
848+
set {maybeIncreasedPriority} to {maybeIncreasedPriority} + 1.
822849
- Let {label} be the value or the variable to {deferDirective}'s {label}
823850
argument.
824-
- Let {deferredGroupedFields} be the result of calling
825-
{CollectFields(objectType, fragmentSelectionSet, variableValues,
826-
visitedFragments, deferredGroupedFieldsList)}.
827-
- Append a record containing {label} and {deferredGroupedFields} to
828-
{deferredGroupedFieldsList}.
829-
- Continue with the next {selection} in {selectionSet}.
830-
- Let {fragmentGroupedFieldSet} be the result of calling
831-
{CollectFields(objectType, fragmentSelectionSet, variableValues,
832-
visitedFragments, deferredGroupedFieldsList)}.
833-
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
834-
- Let {responseKey} be the response key shared by all fields in
835-
{fragmentGroup}.
836-
- Let {groupForResponseKey} be the list in {groupedFields} for
837-
{responseKey}; if no such list exists, create it as an empty list.
838-
- Append all items in {fragmentGroup} to {groupForResponseKey}.
851+
- Let {existingDefer} be the record in {deferredFragments} for {label}.
852+
- If {existingDefer} is undefined:
853+
- Set {maybeNewDefer} equal to a new Deferred Details record created
854+
from {label} and {maybeIncreasedPriority}.
855+
- Set the record in {deferredFragments} for {label} to {maybeNewDefer}.
856+
- Otherwise, set {maybeNewDefer} to {existingDefer}.
857+
- Let {fragmentGroupedFieldSet} and {fragmentDeferredFragments} be the
858+
result of calling {CollectFields(objectType, fragmentSelectionSet,
859+
variableValues, visitedFragments, maybeIncreasedPriority,
860+
parentFieldGroup, maybeNewDefer)}.
861+
- For each {label} and {fragmentDeferredFragment} in
862+
{fragmentDeferredFragments}:
863+
- Let {deferredFragment} be the record in {deferredFragments} for {label}.
864+
- If {deferredFragment} is {undefined}:
865+
- Set the record in {deferredFragments} for {label} to
866+
{fragmentDeferredFragment}.
867+
- For each {responseKey} and {fragmentGroup} in {fragmentGroupedFieldSet}:
868+
- Let {groupForResponseKey} be the record in {groupedFieldSet} for
869+
{responseKey}.
870+
- If {groupForResponseKey} is {undefined}, set the record in
871+
{groupedFieldSet} for {responseKey} to {fragmentGroup}.
872+
- Otherwise:
873+
- Let {fieldGroupPriority} be equal to the {priority} entry on
874+
{fragmentGroup}.
875+
- Let {fragmentGroupPriority} be equal to the {priority} entry on
876+
{fragmentGroup}.
877+
- If {fragmentGroupPriority} is less than {fieldGroupPriority}, update
878+
the {priority} entry on {fieldGroup} to {fragmentGroupPriority}.
879+
- Let {fields} be the corresponding entry on {groupForResponseKey}.
880+
- Let {fragmentFields} be equal to the {fields} entry on
881+
{fragmentGroup}.
882+
- For each {fragmentDeferredFragment} and
883+
{fragmentListForDeferredFragment} in {fragmentFields}:
884+
- Let {label} be the corresponding entry in
885+
{fragmentDeferredFragment}.
886+
- Let {deferredFragment} be the record in {deferredFragments} for
887+
{label}.
888+
- Let {listForDeferredFragment} be the record in {fields} for
889+
{deferredFragment}.
890+
- If {listForDeferredFragment} is {undefined}, set the record in
891+
{fields} for {deferredFragment} to
892+
{fragmentListForDeferredFragment}.
893+
- Otherwise, append all items in {fragmentListForDeferredFragment} to
894+
{listForDeferredFragment}.
839895
- If {selection} is an {InlineFragment}:
840896
- Let {fragmentType} be the type condition on {selection}.
841897
- If {fragmentType} is not {null} and {DoesFragmentTypeApply(objectType,
@@ -848,24 +904,62 @@ deferredGroupedFieldsList):
848904
- Let {deferDirective} be that directive.
849905
- If this execution is for a subscription operation, raise a _field
850906
error_.
907+
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
908+
- Let {maybeNewDefer} be equal to {deferDirective}.
909+
- Let {maybeIncreasedPriority} be equal to {priority}.
851910
- If {deferDirective} is defined:
911+
- If {parentFieldGroup} is {undefined}, set {maybeIncreasedPriority} to 1.
912+
- Otherwise:
913+
- Let {parentFieldGroupPriority} be the value of the {priority} entry on
914+
{parentFieldGroup}.
915+
- If {maybeIncreasedPriority} is equal to {parentFieldGroupPriority},
916+
set {maybeIncreasedPriority} to {maybeIncreasedPriority} + 1.
852917
- Let {label} be the value or the variable to {deferDirective}'s {label}
853918
argument.
854-
- Let {deferredGroupedFields} be the result of calling
855-
{CollectFields(objectType, fragmentSelectionSet, variableValues,
856-
visitedFragments, deferredGroupedFieldsList)}.
857-
- Append a record containing {label} and {deferredGroupedFields} to
858-
{deferredGroupedFieldsList}.
859-
- Continue with the next {selection} in {selectionSet}.
860-
- Let {fragmentGroupedFieldSet} be the result of calling
861-
{CollectFields(objectType, fragmentSelectionSet, variableValues,
862-
visitedFragments, deferredGroupedFieldsList)}.
863-
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
864-
- Let {responseKey} be the response key shared by all fields in
865-
{fragmentGroup}.
866-
- Let {groupForResponseKey} be the list in {groupedFields} for
867-
{responseKey}; if no such list exists, create it as an empty list.
868-
- Append all items in {fragmentGroup} to {groupForResponseKey}.
919+
- Let {existingDefer} be the record in {deferredFragments} for {label}.
920+
- If {existingDefer} is undefined:
921+
- Set {maybeNewDefer} equal to a new Deferred Details record created
922+
from {label} and {maybeIncreasedPriority}.
923+
- Set the record in {deferredFragments} for {label} to {maybeNewDefer}.
924+
- Otherwise, set {maybeNewDefer} to {existingDefer}.
925+
- Let {fragmentGroupedFieldSet} and {fragmentDeferredFragments} be the
926+
result of calling {CollectFields(objectType, fragmentSelectionSet,
927+
variableValues, visitedFragments, maybeIncreasedPriority,
928+
parentFieldGroup, maybeNewDefer)}.
929+
- For each {label} and {fragmentDeferredFragment} in
930+
{fragmentDeferredFragments}:
931+
- Let {deferredFragment} be the record in {deferredFragments} for {label}.
932+
- If {deferredFragment} is {undefined}:
933+
- Set the record in {deferredFragments} for {label} to
934+
{fragmentDeferredFragment}.
935+
- For each {responseKey} and {fragmentGroup} in {fragmentGroupedFieldSet}:
936+
- Let {groupForResponseKey} be the record in {groupedFieldSet} for
937+
{responseKey}.
938+
- If {groupForResponseKey} is {undefined}, set the record in
939+
{groupedFieldSet} for {responseKey} to {fragmentGroup}.
940+
- Otherwise:
941+
- Let {fieldGroupPriority} be equal to the {priority} entry on
942+
{fragmentGroup}.
943+
- Let {fragmentGroupPriority} be equal to the {priority} entry on
944+
{fragmentGroup}.
945+
- If {fragmentGroupPriority} is less than {fieldGroupPriority}, update
946+
the {priority} entry on {fieldGroup} to {fragmentGroupPriority}.
947+
- Let {fields} be the corresponding entry on {groupForResponseKey}.
948+
- Let {fragmentFields} be equal to the {fields} entry on
949+
{fragmentGroup}.
950+
- For each {fragmentDeferredFragment} and
951+
{fragmentListForDeferredFragment} in {fragmentFields}:
952+
- Let {label} be the corresponding entry in
953+
{fragmentDeferredFragment}.
954+
- Let {deferredFragment} be the record in {deferredFragments} for
955+
{label}.
956+
- Let {listForDeferredFragment} be the record in {fields} for
957+
{deferredFragment}.
958+
- If {listForDeferredFragment} is {undefined}, set the record in
959+
{fields} for {deferredFragment} to
960+
{fragmentListForDeferredFragment}.
961+
- Otherwise, append all items in {fragmentListForDeferredFragment} to
962+
{listForDeferredFragment}.
869963
- Return {groupedFields}, {deferredGroupedFieldsList} and {visitedFragments}.
870964

871965
Note: The steps in {CollectFields()} evaluating the `@skip` and `@include`

0 commit comments

Comments
 (0)