Skip to content

Commit 3311df3

Browse files
committed
True nullability schema work in progress
1 parent 3adfcca commit 3311df3

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

spec/Section 2 -- Language.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,12 @@ NonNullType :
12381238

12391239
- NamedType !
12401240
- ListType !
1241+
- NonNullErrorBoundaryType
1242+
1243+
NonNullErrorBoundaryType :
1244+
1245+
- NamedType ! ?
1246+
- ListType ! ?
12411247

12421248
GraphQL describes the types of data expected by arguments and variables. Input
12431249
types may be lists of another input type, or a non-null variant of any other

spec/Section 3 -- Type System.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,11 +1787,16 @@ Following are examples of input coercion with various list types and values:
17871787
## Non-Null
17881788

17891789
By default, all types in GraphQL are nullable; the {null} value is a valid
1790-
response for all of the above types. To declare a type that disallows null, the
1791-
GraphQL Non-Null type can be used. This type wraps an underlying type, and this
1792-
type acts identically to that wrapped type, with the exception that {null} is
1793-
not a valid response for the wrapping type. A trailing exclamation mark is used
1794-
to denote a field that uses a Non-Null type like this: `name: String!`.
1790+
response for all of the above types. To declare a type that is not expected to
1791+
be null, the GraphQL Non-Null type can be used. This type wraps an underlying
1792+
type, and this type acts identically to that wrapped type, with the exception
1793+
that {null} is not an expected response for the wrapping type. A Non-Null type
1794+
may be an error-boundary in which case the response is allowed to be {null}, but
1795+
only with an associated error in the errors array; otherwise {null} is not a
1796+
valid value. A trailing exclamation mark is used to denote a field that uses a
1797+
Non-Null type like this: `name: String!`, and an additional `?` is used to
1798+
indicate that this Non-Null type is an error boundary, like this:
1799+
`name: String!?`.
17951800

17961801
**Nullable vs. Optional**
17971802

@@ -1810,8 +1815,10 @@ always optional and non-null types are always required.
18101815
In all of the above result coercions, {null} was considered a valid value. To
18111816
coerce the result of a Non-Null type, the coercion of the wrapped type should be
18121817
performed. If that result was not {null}, then the result of coercing the
1813-
Non-Null type is that result. If that result was {null}, then a _field error_
1814-
must be raised.
1818+
Non-Null type is that result. If that result was {null}, then: if the Non-Null
1819+
is an error boundary then the result of coercing the Non-Null type is {null} but
1820+
a _field error_ must be collected; otherwise if the Non-Null is not an error
1821+
boundary then a _field error_ must be raised.
18151822

18161823
Note: When a _field error_ is raised on a non-null value, the error propagates
18171824
to the parent field. For more information on this process, see

spec/Section 4 -- Introspection.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ type __Type {
151151
ofType: __Type
152152
# may be non-null for custom SCALAR, otherwise null.
153153
specifiedByURL: String
154+
# must be non-null for NON_NULL, otherwise null.
155+
isErrorBoundary: Boolean
154156
}
155157

156158
enum __TypeKind {
@@ -168,7 +170,7 @@ type __Field {
168170
name: String!
169171
description: String
170172
args(includeDeprecated: Boolean = false): [__InputValue!]!
171-
type: __Type!
173+
type(includeErrorBoundaries: Boolean! = false): __Type!
172174
isDeprecated: Boolean!
173175
deprecationReason: String
174176
}
@@ -395,8 +397,13 @@ Fields\:
395397
GraphQL types are nullable. The value {null} is a valid response for field type.
396398

397399
A Non-Null type is a type modifier: it wraps another type instance in the
398-
`ofType` field. Non-null types do not allow {null} as a response, and indicate
399-
required inputs for arguments and input object fields.
400+
`ofType` field. A Non-Null type may opt to be an error boundary, in which case
401+
it indicates that the value is not expected to be null: it will only be null in
402+
the case of an error (either it's own, or one of its children). For error
403+
boundary non-null types, the `null` value will not "bubble". Error boundary
404+
non-null types are only allowed in output positions. Non-null types that are not
405+
error boundaries do not allow {null} as a response, and indicate required inputs
406+
for arguments and input object fields.
400407

401408
The modified type in the `ofType` field may itself be a modified List type,
402409
allowing the representation of Non-Null of Lists. However it must not be a
@@ -406,6 +413,8 @@ Fields\:
406413

407414
- `kind` must return `__TypeKind.NON_NULL`.
408415
- `ofType` must return a type of any kind except Non-Null.
416+
- `isErrorBoundary` must return true if this Non-Null is an error boundary,
417+
false otherwise.
409418
- All other fields must return {null}.
410419

411420
### The \_\_Field Type
@@ -422,6 +431,10 @@ Fields\:
422431
{true}, deprecated arguments are also returned.
423432
- `type` must return a `__Type` that represents the type of value returned by
424433
this field.
434+
- Accepts the argument `includeErrorBoundaries` which defaults to {false}. If
435+
{false} then the field will instead return a `__Type` that represents the
436+
type of value returned by this field with all error-boundary non-null type
437+
modifiers removed. This is for backwards compatibility.
425438
- `isDeprecated` returns {true} if this field should no longer be used,
426439
otherwise {false}.
427440
- `deprecationReason` optionally provides a reason why this field is deprecated.

spec/Section 6 -- Execution.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,10 @@ CompleteValue(fieldType, fields, result, variableValues):
674674
- Let {innerType} be the inner type of {fieldType}.
675675
- Let {completedResult} be the result of calling {CompleteValue(innerType,
676676
fields, result, variableValues)}.
677-
- If {completedResult} is {null}, raise a _field error_.
677+
- If {completedResult} is {null}:
678+
- If {fieldType} is an error boundary, collect a _field error_ and return
679+
{null}.
680+
- Otherwise, raise a _field error_.
678681
- Return {completedResult}.
679682
- If {result} is {null} (or another internal value similar to {null} such as
680683
{undefined}), return {null}.

0 commit comments

Comments
 (0)