Skip to content

Commit 4c8a02b

Browse files
committed
Remove SemanticNonNull from TypeNode
This type is reused for variables, inputs and list-types which can't be smantically non-null. list-types can be but only if they are used in an SDL context. This is kind of a short-coming of our types, we conflate SDL and execution language.
1 parent 2321f93 commit 4c8a02b

File tree

5 files changed

+22
-49
lines changed

5 files changed

+22
-49
lines changed

src/execution/__tests__/semantic-nullability-test.ts

+7-24
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ describe('Execute: Handles Semantic Nullability', () => {
3636

3737
it('SemanticNonNull throws error on null without error', async () => {
3838
const data = {
39-
a: () => 'Apple',
4039
b: () => null,
41-
c: () => 'Cookie',
4240
};
4341

4442
const document = parse(`
@@ -53,11 +51,8 @@ describe('Execute: Handles Semantic Nullability', () => {
5351
rootValue: data,
5452
});
5553

56-
const executable = document.definitions?.values().next()
57-
.value as ExecutableDefinitionNode;
58-
const selectionSet = executable.selectionSet.selections
59-
.values()
60-
.next().value;
54+
const executable = document.definitions[0] as ExecutableDefinitionNode;
55+
const selectionSet = executable.selectionSet.selections[0];
6156

6257
expect(result).to.deep.equal({
6358
data: {
@@ -77,11 +72,9 @@ describe('Execute: Handles Semantic Nullability', () => {
7772

7873
it('SemanticNonNull succeeds on null with error', async () => {
7974
const data = {
80-
a: () => 'Apple',
8175
b: () => {
8276
throw new Error('Something went wrong');
8377
},
84-
c: () => 'Cookie',
8578
};
8679

8780
const document = parse(`
@@ -90,11 +83,8 @@ describe('Execute: Handles Semantic Nullability', () => {
9083
}
9184
`);
9285

93-
const executable = document.definitions?.values().next()
94-
.value as ExecutableDefinitionNode;
95-
const selectionSet = executable.selectionSet.selections
96-
.values()
97-
.next().value;
86+
const executable = document.definitions[0] as ExecutableDefinitionNode;
87+
const selectionSet = executable.selectionSet.selections[0];
9888

9989
const result = await execute({
10090
schema: new GraphQLSchema({ query: DataType }),
@@ -121,9 +111,6 @@ describe('Execute: Handles Semantic Nullability', () => {
121111
};
122112

123113
const data = {
124-
a: () => 'Apple',
125-
b: () => null,
126-
c: () => 'Cookie',
127114
d: () => deepData,
128115
};
129116

@@ -141,13 +128,9 @@ describe('Execute: Handles Semantic Nullability', () => {
141128
rootValue: data,
142129
});
143130

144-
const executable = document.definitions?.values().next()
145-
.value as ExecutableDefinitionNode;
146-
const dSelectionSet = executable.selectionSet.selections.values().next()
147-
.value as FieldNode;
148-
const fSelectionSet = dSelectionSet.selectionSet?.selections
149-
.values()
150-
.next().value;
131+
const executable = document.definitions[0] as ExecutableDefinitionNode;
132+
const dSelectionSet = executable.selectionSet.selections[0] as FieldNode;
133+
const fSelectionSet = dSelectionSet.selectionSet?.selections[0];
151134

152135
expect(result).to.deep.equal({
153136
data: {

src/language/ast.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -529,11 +529,7 @@ export interface SemanticNonNullTypeNode {
529529

530530
/** Type Reference */
531531

532-
export type TypeNode =
533-
| NamedTypeNode
534-
| ListTypeNode
535-
| NonNullTypeNode
536-
| SemanticNonNullTypeNode;
532+
export type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode;
537533

538534
export interface NamedTypeNode {
539535
readonly kind: Kind.NAMED_TYPE;
@@ -544,7 +540,7 @@ export interface NamedTypeNode {
544540
export interface ListTypeNode {
545541
readonly kind: Kind.LIST_TYPE;
546542
readonly loc?: Location;
547-
readonly type: TypeNode;
543+
readonly type: TypeNode | SemanticNonNullTypeNode;
548544
}
549545

550546
export interface NonNullTypeNode {
@@ -609,7 +605,7 @@ export interface FieldDefinitionNode {
609605
readonly description?: StringValueNode;
610606
readonly name: NameNode;
611607
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
612-
readonly type: TypeNode;
608+
readonly type: TypeNode | SemanticNonNullTypeNode;
613609
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
614610
}
615611

src/language/parser.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export function parseConstValue(
184184
export function parseType(
185185
source: string | Source,
186186
options?: ParseOptions | undefined,
187-
): TypeNode {
187+
): TypeNode | SemanticNonNullTypeNode {
188188
const parser = new Parser(source, options);
189189
parser.expectToken(TokenKind.SOF);
190190
const type = parser.parseTypeReference();
@@ -403,7 +403,8 @@ export class Parser {
403403
return this.node<VariableDefinitionNode>(this._lexer.token, {
404404
kind: Kind.VARIABLE_DEFINITION,
405405
variable: this.parseVariable(),
406-
type: (this.expectToken(TokenKind.COLON), this.parseTypeReference()),
406+
type: (this.expectToken(TokenKind.COLON),
407+
this.parseTypeReference()) as TypeNode,
407408
defaultValue: this.expectOptionalToken(TokenKind.EQUALS)
408409
? this.parseConstValueLiteral()
409410
: undefined,
@@ -773,15 +774,15 @@ export class Parser {
773774
* - ListType
774775
* - NonNullType
775776
*/
776-
parseTypeReference(): TypeNode {
777+
parseTypeReference(): TypeNode | SemanticNonNullTypeNode {
777778
const start = this._lexer.token;
778779
let type;
779780
if (this.expectOptionalToken(TokenKind.BRACKET_L)) {
780781
const innerType = this.parseTypeReference();
781782
this.expectToken(TokenKind.BRACKET_R);
782783
type = this.node<ListTypeNode>(start, {
783784
kind: Kind.LIST_TYPE,
784-
type: innerType,
785+
type: innerType as TypeNode,
785786
});
786787
} else {
787788
type = this.parseNamedType();
@@ -992,7 +993,7 @@ export class Parser {
992993
kind: Kind.INPUT_VALUE_DEFINITION,
993994
description,
994995
name,
995-
type,
996+
type: type as TypeNode,
996997
defaultValue,
997998
directives,
998999
});

src/utilities/extendSchema.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
ScalarTypeExtensionNode,
2525
SchemaDefinitionNode,
2626
SchemaExtensionNode,
27+
SemanticNonNullTypeNode,
2728
TypeDefinitionNode,
2829
TypeNode,
2930
UnionTypeDefinitionNode,
@@ -431,7 +432,9 @@ export function extendSchemaImpl(
431432
return type;
432433
}
433434

434-
function getWrappedType(node: TypeNode): GraphQLType {
435+
function getWrappedType(
436+
node: TypeNode | SemanticNonNullTypeNode,
437+
): GraphQLType {
435438
if (node.kind === Kind.LIST_TYPE) {
436439
return new GraphQLList(getWrappedType(node.type));
437440
}

src/utilities/typeFromAST.ts

+2-12
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ import type {
77
import { Kind } from '../language/kinds';
88

99
import type { GraphQLNamedType, GraphQLType } from '../type/definition';
10-
import {
11-
GraphQLList,
12-
GraphQLNonNull,
13-
GraphQLSemanticNonNull,
14-
} from '../type/definition';
10+
import { GraphQLList, GraphQLNonNull } from '../type/definition';
1511
import type { GraphQLSchema } from '../type/schema';
1612

1713
/**
@@ -43,19 +39,13 @@ export function typeFromAST(
4339
): GraphQLType | undefined {
4440
switch (typeNode.kind) {
4541
case Kind.LIST_TYPE: {
46-
const innerType = typeFromAST(schema, typeNode.type);
42+
const innerType = typeFromAST(schema, typeNode.type as TypeNode);
4743
return innerType && new GraphQLList(innerType);
4844
}
4945
case Kind.NON_NULL_TYPE: {
5046
const innerType = typeFromAST(schema, typeNode.type);
5147
return innerType && new GraphQLNonNull(innerType);
5248
}
53-
// We only use typeFromAST for fragment/variable type inference
54-
// which should not be affected by semantic non-null types
55-
// case Kind.SEMANTIC_NON_NULL_TYPE: {
56-
// const innerType = typeFromAST(schema, typeNode.type);
57-
// return innerType && new GraphQLSemanticNonNull(innerType);
58-
// }
5949
case Kind.NAMED_TYPE:
6050
return schema.getType(typeNode.name.value);
6151
}

0 commit comments

Comments
 (0)