diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 8f51c9b80e..ac24a5910c 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -24,6 +24,7 @@ import LValParser from "./lval"; import { isStrictReservedWord, isStrictBindReservedWord, + isKeyword, } from "../util/identifier"; import type { Pos, Position } from "../util/location"; import * as charCodes from "charcodes"; @@ -2020,7 +2021,7 @@ export default class ExpressionParser extends LValParser { ); } - if (this.isReservedWord(word) || (checkKeywords && this.isKeyword(word))) { + if (this.isReservedWord(word) || (checkKeywords && isKeyword(word))) { this.raise(startLoc, word + " is a reserved word"); } } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index 878cc4c308..16543413a5 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -1190,9 +1190,6 @@ export default (superClass: Class): Class => case "any": return this.finishNode(node, "AnyTypeAnnotation"); - case "void": - return this.finishNode(node, "VoidTypeAnnotation"); - case "bool": case "boolean": return this.finishNode(node, "BooleanTypeAnnotation"); @@ -1369,6 +1366,10 @@ export default (superClass: Class): Class => "NumberLiteralTypeAnnotation", ); + case tt._void: + this.next(); + return this.finishNode(node, "VoidTypeAnnotation"); + case tt._null: this.next(); return this.finishNode(node, "NullLiteralTypeAnnotation"); @@ -1922,16 +1923,6 @@ export default (superClass: Class): Class => } } - // don't consider `void` to be a keyword as then it'll use the void token type - // and set startExpr - isKeyword(name: string): boolean { - if (this.state.inType && name === "void") { - return false; - } else { - return super.isKeyword(name); - } - } - // ensure that inside flow types, we bypass the jsx parser plugin getTokenFromCode(code: number): void { const next = this.state.input.charCodeAt(this.state.pos + 1); diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index 4b5a7adc49..d527c96913 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -3,11 +3,7 @@ import type { Options } from "../options"; import type { Position } from "../util/location"; import * as charCodes from "charcodes"; -import { - isIdentifierStart, - isIdentifierChar, - isKeyword, -} from "../util/identifier"; +import { isIdentifierStart, isIdentifierChar } from "../util/identifier"; import { types as tt, keywords as keywordTypes, type TokenType } from "./types"; import { type TokContext, types as ct } from "./context"; import LocationParser from "../parser/location"; @@ -157,12 +153,6 @@ export default class Tokenizer extends LocationParser { // TODO - isKeyword(word: string): boolean { - return isKeyword(word); - } - - // TODO - lookahead(): State { const old = this.state; this.state = old.clone(true); @@ -1336,14 +1326,10 @@ export default class Tokenizer extends LocationParser { readWord(): void { const word = this.readWord1(); - let type = tt.name; + const type = keywordTypes[word] || tt.name; - if (this.isKeyword(word)) { - if (this.state.containsEsc) { - this.raise(this.state.pos, `Escape sequence in keyword ${word}`); - } - - type = keywordTypes[word]; + if (type.keyword && this.state.containsEsc) { + this.raise(this.state.pos, `Escape sequence in keyword ${word}`); } // Allow @@iterator and @@asyncIterator as a identifier only inside type diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 5212e62608..6775ee5375 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -133,20 +133,20 @@ export const types: { [name: string]: TokenType } = { incDec: new TokenType("++/--", { prefix, postfix, startsExpr }), bang: new TokenType("!", { beforeExpr, prefix, startsExpr }), tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }), - pipeline: new BinopTokenType("|>", 0), - nullishCoalescing: new BinopTokenType("??", 1), - logicalOR: new BinopTokenType("||", 1), - logicalAND: new BinopTokenType("&&", 2), - bitwiseOR: new BinopTokenType("|", 3), - bitwiseXOR: new BinopTokenType("^", 4), - bitwiseAND: new BinopTokenType("&", 5), - equality: new BinopTokenType("==/!=", 6), - relational: new BinopTokenType("", 7), - bitShift: new BinopTokenType("<>", 8), + pipeline: BinopTokenType("|>", 0), + nullishCoalescing: BinopTokenType("??", 1), + logicalOR: BinopTokenType("||", 1), + logicalAND: BinopTokenType("&&", 2), + bitwiseOR: BinopTokenType("|", 3), + bitwiseXOR: BinopTokenType("^", 4), + bitwiseAND: BinopTokenType("&", 5), + equality: BinopTokenType("==/!=", 6), + relational: BinopTokenType("", 7), + bitShift: BinopTokenType("<>", 8), plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }), - modulo: new BinopTokenType("%", 10), - star: new BinopTokenType("*", 10), - slash: new BinopTokenType("/", 10), + modulo: BinopTokenType("%", 10), + star: BinopTokenType("*", 10), + slash: BinopTokenType("/", 10), exponent: new TokenType("**", { beforeExpr, binop: 11, @@ -154,45 +154,53 @@ export const types: { [name: string]: TokenType } = { }), }; -export const keywords = { - break: new KeywordTokenType("break"), - case: new KeywordTokenType("case", { beforeExpr }), - catch: new KeywordTokenType("catch"), - continue: new KeywordTokenType("continue"), - debugger: new KeywordTokenType("debugger"), - default: new KeywordTokenType("default", { beforeExpr }), - do: new KeywordTokenType("do", { isLoop, beforeExpr }), - else: new KeywordTokenType("else", { beforeExpr }), - finally: new KeywordTokenType("finally"), - for: new KeywordTokenType("for", { isLoop }), - function: new KeywordTokenType("function", { startsExpr }), - if: new KeywordTokenType("if"), - return: new KeywordTokenType("return", { beforeExpr }), - switch: new KeywordTokenType("switch"), - throw: new KeywordTokenType("throw", { beforeExpr, prefix, startsExpr }), - try: new KeywordTokenType("try"), - var: new KeywordTokenType("var"), - let: new KeywordTokenType("let"), - const: new KeywordTokenType("const"), - while: new KeywordTokenType("while", { isLoop }), - with: new KeywordTokenType("with"), - new: new KeywordTokenType("new", { beforeExpr, startsExpr }), - this: new KeywordTokenType("this", { startsExpr }), - super: new KeywordTokenType("super", { startsExpr }), - class: new KeywordTokenType("class", { startsExpr }), - extends: new KeywordTokenType("extends", { beforeExpr }), - export: new KeywordTokenType("export"), - import: new KeywordTokenType("import", { startsExpr }), - yield: new KeywordTokenType("yield", { beforeExpr, startsExpr }), - null: new KeywordTokenType("null", { startsExpr }), - true: new KeywordTokenType("true", { startsExpr }), - false: new KeywordTokenType("false", { startsExpr }), - in: new KeywordTokenType("in", { beforeExpr, binop: 7 }), - instanceof: new KeywordTokenType("instanceof", { beforeExpr, binop: 7 }), - typeof: new KeywordTokenType("typeof", { beforeExpr, prefix, startsExpr }), - void: new KeywordTokenType("void", { beforeExpr, prefix, startsExpr }), - delete: new KeywordTokenType("delete", { beforeExpr, prefix, startsExpr }), -}; +function makeKeywordProps( + name: string, + conf: any, +): PropertyDescriptor { + return { value: KeywordTokenType(name, conf), enumerable: true }; +} + +// $FlowIssue +export const keywords = Object.create(null, { + break: makeKeywordProps("break"), + case: makeKeywordProps("case", { beforeExpr }), + catch: makeKeywordProps("catch"), + continue: makeKeywordProps("continue"), + debugger: makeKeywordProps("debugger"), + default: makeKeywordProps("default", { beforeExpr }), + do: makeKeywordProps("do", { isLoop, beforeExpr }), + else: makeKeywordProps("else", { beforeExpr }), + finally: makeKeywordProps("finally"), + for: makeKeywordProps("for", { isLoop }), + function: makeKeywordProps("function", { startsExpr }), + if: makeKeywordProps("if"), + return: makeKeywordProps("return", { beforeExpr }), + switch: makeKeywordProps("switch"), + throw: makeKeywordProps("throw", { beforeExpr, prefix, startsExpr }), + try: makeKeywordProps("try"), + var: makeKeywordProps("var"), + let: makeKeywordProps("let"), + const: makeKeywordProps("const"), + while: makeKeywordProps("while", { isLoop }), + with: makeKeywordProps("with"), + new: makeKeywordProps("new"), + this: makeKeywordProps("this", { startsExpr }), + super: makeKeywordProps("super", { startsExpr }), + class: makeKeywordProps("class", { startsExpr }), + extends: makeKeywordProps("extends", { beforeExpr }), + export: makeKeywordProps("export"), + import: makeKeywordProps("import", { startsExpr }), + yield: makeKeywordProps("yield", { beforeExpr, startsExpr }), + null: makeKeywordProps("null", { startsExpr }), + true: makeKeywordProps("true", { startsExpr }), + false: makeKeywordProps("false", { startsExpr }), + in: makeKeywordProps("in", { beforeExpr, binop: 7 }), + instanceof: makeKeywordProps("instanceof", { beforeExpr, binop: 7 }), + typeof: makeKeywordProps("typeof", { beforeExpr, prefix, startsExpr }), + void: makeKeywordProps("void", { beforeExpr, prefix, startsExpr }), + delete: makeKeywordProps("delete", { beforeExpr, prefix, startsExpr }), +}); // Map keyword names to token types. Object.keys(keywords).forEach(name => {