diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index ffdfe11b46..8cbfe16c95 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -120,6 +120,26 @@ describe('Parser', () => { }); }); + it('does not allow "true", "false", or "null" as enum value', () => { + expectSyntaxError('enum Test { VALID, true }').to.deep.equal({ + message: + 'Syntax Error: Name "true" is reserved and cannot be used for an enum value.', + locations: [{ line: 1, column: 20 }], + }); + + expectSyntaxError('enum Test { VALID, false }').to.deep.equal({ + message: + 'Syntax Error: Name "false" is reserved and cannot be used for an enum value.', + locations: [{ line: 1, column: 20 }], + }); + + expectSyntaxError('enum Test { VALID, null }').to.deep.equal({ + message: + 'Syntax Error: Name "null" is reserved and cannot be used for an 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/parser.ts b/src/language/parser.ts index 7095cad1d1..9ecd045670 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.parseEnumValueName(); const directives = this.parseConstDirectives(); return this.node(start, { kind: Kind.ENUM_VALUE_DEFINITION, @@ -1052,6 +1050,26 @@ export class Parser { }); } + /** + * EnumValue : Name but not `true`, `false` or `null` + */ + parseEnumValueName(): NameNode { + if ( + this._lexer.token.value === 'true' || + this._lexer.token.value === 'false' || + this._lexer.token.value === 'null' + ) { + throw syntaxError( + this._lexer.source, + this._lexer.token.start, + `${getTokenDesc( + this._lexer.token, + )} is reserved and cannot be used for an enum value.`, + ); + } + return this.parseName(); + } + /** * InputObjectTypeDefinition : * - Description? input Name Directives[Const]? InputFieldsDefinition?