From aa52fdba598ce3add23cf5ed0f32393f51925c54 Mon Sep 17 00:00:00 2001 From: Jan Melcher Date: Wed, 4 Aug 2021 10:09:33 +0200 Subject: [PATCH] BREAKING: Disallow "true", "false", and "null" as enum values The specification disallows these in the SDL grammar definition, and using one of these enum values would result in a schema that would throw validation errors on creation. Fixes #3221. --- src/language/__tests__/parser-test.ts | 7 +++++ src/language/__tests__/schema-parser-test.ts | 6 ++++- src/language/ast.ts | 2 +- src/language/parser.ts | 27 +++++++++++++++++--- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index ffdfe11b461..534f76fb348 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -120,6 +120,13 @@ describe('Parser', () => { }); }); + it('does not allow "true" as enum value', () => { + expectSyntaxError('enum Test { VALID, true }').to.deep.equal({ + message: 'Syntax Error: Name "true" is not a valid enum value.', + locations: [{ line: 1, column: 20 }], + }); + }); + it('parses multi-byte characters', () => { // Note: \u0A0A could be naively interpreted as two line-feed chars. const ast = parse(` diff --git a/src/language/__tests__/schema-parser-test.ts b/src/language/__tests__/schema-parser-test.ts index e596bba35dc..78fb429454a 100644 --- a/src/language/__tests__/schema-parser-test.ts +++ b/src/language/__tests__/schema-parser-test.ts @@ -52,7 +52,11 @@ function fieldNodeWithArgs( function enumValueNode(name: unknown, loc: unknown) { return { kind: 'EnumValueDefinition', - name: nameNode(name, loc), + name: { + kind: 'EnumValue', + value: name, + loc, + }, description: undefined, directives: [], loc, diff --git a/src/language/ast.ts b/src/language/ast.ts index ccb6240111a..0429c569a8c 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -584,7 +584,7 @@ export interface EnumValueDefinitionNode { readonly kind: 'EnumValueDefinition'; readonly loc?: Location; readonly description?: StringValueNode; - readonly name: NameNode; + readonly name: EnumValueNode; readonly directives?: ReadonlyArray; } diff --git a/src/language/parser.ts b/src/language/parser.ts index 7095cad1d11..d93cb14a1f2 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -1036,13 +1036,11 @@ export class Parser { /** * EnumValueDefinition : Description? EnumValue Directives[Const]? - * - * EnumValue : Name */ parseEnumValueDefinition(): EnumValueDefinitionNode { const start = this._lexer.token; const description = this.parseDescription(); - const name = this.parseName(); + const name = this.parseEnumValue(); const directives = this.parseConstDirectives(); return this.node(start, { kind: Kind.ENUM_VALUE_DEFINITION, @@ -1052,6 +1050,29 @@ export class Parser { }); } + /** + * EnumValue : Name but not `true`, `false` or `null` + */ + parseEnumValue(): EnumValueNode { + const node = this.parseName(); + if ( + node.value === 'true' || + node.value === 'false' || + node.value === 'null' + ) { + throw syntaxError( + this._lexer.source, + this._lexer.lastToken.start, + `${getTokenDesc(this._lexer.lastToken)} is not a valid enum value.`, + ); + } + return { + kind: 'EnumValue', + value: node.value, + loc: node.loc, + }; + } + /** * InputObjectTypeDefinition : * - Description? input Name Directives[Const]? InputFieldsDefinition?