@@ -564,30 +564,49 @@ Each field requested in the grouped field set that is defined on the selected
564564objectType will result in an entry in the response map. Field execution first
565565coerces any provided argument values, then resolves a value for the field, and
566566finally completes that value either by recursively executing another selection
567- set or coercing a scalar value.
567+ set or coercing a scalar value. ` ccnPropagationPairs ` is an unordered map where
568+ the keys are paths of required fields, and values are paths of the nearest
569+ optional parent to those required fields. ` currentPropagationPath ` starts as an
570+ empty path to indicate that ` null ` propagation should continue until it hits
571+ ` data ` if there is no optional field.
568572
569- ExecuteField(objectType, objectValue, fieldType, fields, variableValues):
573+ ExecuteField(objectType, objectValue, fieldType, fields, variableValues,
574+ currentPropagationPath, ccnPropagationPairs):
570575
571576- Let {field} be the first entry in {fields}.
572577- Let {fieldName} be the field name of {field}.
573578- Let {requiredStatus} be the required status of {field}.
579+ - Let {newPropagationPath} be {path} if {requiredStatus} is optional, otherwise
580+ let {newPropagationPath} be {currentPropagationPath}
581+ - If {requiredStatus} is optional:
582+ - Let {newPropagationPath} be {path}
583+ - If {requiredStatus} is required:
584+ - Set {path} to {newPropagationPath} in {ccnPropagationPairs}
574585- Let {argumentValues} be the result of {CoerceArgumentValues(objectType, field,
575586 variableValues)}
576587- Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName,
577588 argumentValues)}.
578- - Let {modifiedFieldType} be {ModifiedOutputType (fieldType, requiredStatus)}.
589+ - Let {modifiedFieldType} be {ApplyRequiredStatus (fieldType, requiredStatus)}.
579590- Return the result of {CompleteValue(modifiedFieldType, fields, resolvedValue,
580- variableValues)}.
591+ variableValues, newPropagationPath, ccnPropagationPairs )}.
581592
582593## Accounting For Client Controlled Nullability Designators
583594
584595A field can have its nullability status set either in its service's schema, or a
585- nullability designator (! or ? ) can override it for the duration of an
596+ nullability designator (` ! ` or ` ? ` ) can override it for the duration of an
586597execution. In order to determine a field's true nullability, both are taken into
587- account and a final type is produced.
588-
589- ModifiedOutputType(outputType, requiredStatus):
590-
598+ account and a final type is produced. A field marked with a ` ! ` is called a
599+ "required field" and a field marked with a ` ? ` is called an optional field.
600+
601+ ApplyRequiredStatus(type, requiredStatus):
602+
603+ - If there is no {requiredStatus}:
604+ - return {type}
605+ - If {requiredStatus} is not a list:
606+ - If {requiredStatus} is required:
607+ - return a ` Non-Null ` version of {type}
608+ - If {requiredStatus} is optional:
609+ - return a nullable version of {type}
591610- Create a {stack} initially containing {type}.
592611- As long as the top of {stack} is a list:
593612 - Let {currentType} be the top item of {stack}.
@@ -616,8 +635,8 @@ ModifiedOutputType(outputType, requiredStatus):
616635 - If the nullable type of {listType} is not a list
617636 - Pop the top of {stack} and set {listType} to the result
618637 - If {listType} does not exist:
619- - Throw an error because {requiredStatus} had more list dimensions than
620- {outputType} and is invalid.
638+ - Raise a field error because {requiredStatus} had more list dimensions
639+ than {outputType} and is invalid.
621640 - If {resultingType} exist:
622641 - If {listType} is Non-Nullable:
623642 - Set {resultingType} to a Non-Nullable list where the element is
@@ -627,11 +646,9 @@ ModifiedOutputType(outputType, requiredStatus):
627646 - Continue onto the next node.
628647 - Set {resultingType} to {listType}
629648- If {stack} is not empty:
630- - Throw an error because {requiredStatus} had fewer list dimensions than
649+ - Raise a field error because {requiredStatus} had fewer list dimensions than
631650 {outputType} and is invalid.
632651- Return {resultingType}.
633- - Otherwise:
634- - Return {outputType}.
635652
636653### Coercing Field Arguments
637654
@@ -835,8 +852,9 @@ response.
835852
836853If the result of resolving a field is {null} (either because the function to
837854resolve the field returned {null} or because a field error was raised), and the
838- {ModifiedOutputType} of that field is of a ` Non-Null ` type, then a field error
839- is raised. The error must be added to the {"errors"} list in the response.
855+ type of the field after {ApplyRequiredStatus} has been applied to it is of a
856+ ` Non-Null ` type, then a field error is raised. The error must be added to the
857+ {"errors"} list in the response.
840858
841859If the field returns {null} because of a field error which has already been
842860added to the {"errors"} list in the response, the {"errors"} list must not be
@@ -845,8 +863,11 @@ field.
845863
846864Since ` Non-Null ` type fields cannot be {null}, field errors are propagated to be
847865handled by the parent field. If the parent field may be {null} then it resolves
848- to {null}, otherwise if its {ModifiedOutputType} is a ` Non-Null ` type, the field
849- error is further propagated to its parent field.
866+ to {null}, otherwise if it is a ` Non-Null ` type, the field error is further
867+ propagated to its parent field.
868+
869+ If a required field resolves to {null}, propagation instead happens until an
870+ optional field is found.
850871
851872If a ` List ` type wraps a ` Non-Null ` type, and one of the elements of that list
852873resolves to {null}, then the entire list must resolve to {null}. If the ` List `
0 commit comments