From ee0605677902127d598e1287acca839bc2badc53 Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Tue, 10 Sep 2019 22:35:21 -0700 Subject: [PATCH] RFC: Number lexer lookahead restriction Implements and adds the tests described by https://github.com/graphql/graphql-spec/pull/601 --- src/language/__tests__/lexer-test.js | 35 ++++++++++++++++++++++++++++ src/language/lexer.js | 11 +++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/language/__tests__/lexer-test.js b/src/language/__tests__/lexer-test.js index 974f003408..cb98d0978f 100644 --- a/src/language/__tests__/lexer-test.js +++ b/src/language/__tests__/lexer-test.js @@ -708,6 +708,41 @@ describe('Lexer', () => { ); }); + it('lex does not allow name-start after a number', () => { + expectSyntaxError('0xF1', 'Invalid number, expected digit but got: "x".', { + line: 1, + column: 2, + }); + expectSyntaxError('0b10', 'Invalid number, expected digit but got: "b".', { + line: 1, + column: 2, + }); + expectSyntaxError( + '123abc', + 'Invalid number, expected digit but got: "a".', + { line: 1, column: 4 }, + ); + expectSyntaxError('1_234', 'Invalid number, expected digit but got: "_".', { + line: 1, + column: 2, + }); + expect(() => lexSecond('1ß')).to.throw( + 'Syntax Error: Cannot parse the unexpected character "\\u00DF".', + ); + expectSyntaxError('1.23f', 'Invalid number, expected digit but got: "f".', { + line: 1, + column: 5, + }); + expectSyntaxError( + '1.234_5', + 'Invalid number, expected digit but got: "_".', + { line: 1, column: 6 }, + ); + expect(() => lexSecond('1.2ß')).to.throw( + 'Syntax Error: Cannot parse the unexpected character "\\u00DF".', + ); + }); + it('lexes punctuation', () => { expect(lexOne('!')).to.contain({ kind: TokenKind.BANG, diff --git a/src/language/lexer.js b/src/language/lexer.js index f2f3dfa377..577255ef72 100644 --- a/src/language/lexer.js +++ b/src/language/lexer.js @@ -447,8 +447,8 @@ function readNumber(source, start, firstCode, line, col, prev): Token { code = body.charCodeAt(position); } - // Numbers cannot be followed by . or e - if (code === 46 || code === 69 || code === 101) { + // Numbers cannot be followed by . or NameStart + if (code === 46 || isNameStart(code)) { throw syntaxError( source, position, @@ -738,3 +738,10 @@ function readName(source, start, line, col, prev): Token { body.slice(start, position), ); } + +// _ A-Z a-z +function isNameStart(code): boolean { + return ( + code === 95 || (code >= 65 && code <= 90) || (code >= 97 && code <= 122) + ); +}