@@ -579,22 +579,52 @@ ExecuteField(objectType, objectValue, fieldType, fields, variableValues):
579579## Accounting For Client Controlled Nullability Designators
580580
581581A field can have its nullability status set either in its service's schema, or
582- it can be overriden by a designator (! or ?) for the duration of an execution.
582+ a nullability designator (! or ?) can override it for the duration of an execution.
583583In order to determine a field's true nullability, both are taken into account
584584and a final type is produced.
585585
586586ModifiedOutputType(outputType, requiredStatus):
587587
588- - If {requiredStatus} is 'required' and {outputType} is not a Non-Nullable type:
589- - Return Non-Null with an inner type of {outputType}.
590- - Otherwise if {requiredStatus} is 'optional':
591- - If {outputType} is not a Non-Nullable type:
592- - Return {outputType}.
593- - Otherwise if {outputType} is a Non-Nullable type:
594- - Let {innerOutputType} be the inner type of {outputType}.
595- - Return {innerOutputType}.
596- - Otherwise:
597- - Return {outputType}.
588+ - Create a {stack} initially containing {type}.
589+ - As long as the top of {stack} is a list:
590+ - Let {currentType} be the top item of {stack}.
591+ - Push the {elementType} of {currentType} to the {stack}.
592+ - If {requiredStatus} exists:
593+ - Start visiting {node}s in {requiredStatus} and building up a {resultingType}:
594+ - For each {node} that is a RequiredDesignator:
595+ - If {resultingType} exists:
596+ - Let {nullableResult} be the nullable type of {resultingType}.
597+ - Set {resultingType} to the Non-Nullable type of {nullableResult}.
598+ - Continue onto the next node.
599+ - Pop the top of {stack} and let {nextType} be the result.
600+ - Let {nullableType} be the nullable type of {nextType}.
601+ - Set {resultingType} to the Non-Nullable type of {nullableType}.
602+ - Continue onto the next node.
603+ - For each {node} that is a OptionalDesignator:
604+ - If {resultingType} exists:
605+ - Set {resultingType} to the nullableType type of {resultingType}.
606+ - Continue onto the next node.
607+ - Pop the top of {stack} and let {nextType} be the result.
608+ - Set {resultingType} to the nullable type of {resultingType}
609+ - Continue onto the next node.
610+ - For each {node} that is a ListNullabilityDesignator:
611+ - Pop the top of {stack} and let {listType} be the result
612+ - If the nullable type of {listType} is not a list
613+ - Pop the top of {stack} and set {listType} to the result
614+ - If {listType} does not exist:
615+ - Throw an error because {requiredStatus} had more list dimensions than {outputType} and is invalid.
616+ - If {resultingType} exist:
617+ - If {listType} is Non-Nullable:
618+ - Set {resultingType} to a Non-Nullable list where the element is {resultingType}.
619+ - Otherwise:
620+ - Set {resultingType} to a list where the element is {resultingType}.
621+ - Continue onto the next node.
622+ - Set {resultingType} to {listType}
623+ - If {stack} is not empty:
624+ - Throw an error because {requiredStatus} had fewer list dimensions than {outputType} and is invalid.
625+ - Return {resultingType}.
626+ - Otherwise:
627+ - Return {outputType}.
598628
599629### Coercing Field Arguments
600630
0 commit comments