perf: Use === or Set.has instead of array.indexOf for keyword checks

This commit is contained in:
Daniel Tschinder 2019-01-17 00:46:43 -08:00
parent f12905b531
commit b66d921053
4 changed files with 89 additions and 24 deletions

View File

@ -1,7 +1,7 @@
// @flow
import type { Options } from "../options";
import { reservedWords } from "../util/identifier";
import { isES2015ReservedWord } from "../util/identifier";
import type State from "../tokenizer/state";
import type { PluginsMap } from "./index";
@ -21,7 +21,7 @@ export default class BaseParser {
if (word === "await") {
return this.inModule;
} else {
return reservedWords[6](word);
return isES2015ReservedWord(word);
}
}

View File

@ -21,7 +21,10 @@
import { types as tt, type TokenType } from "../tokenizer/types";
import * as N from "../types";
import LValParser from "./lval";
import { reservedWords } from "../util/identifier";
import {
isStrictReservedWord,
isStrictBindReservedWord,
} from "../util/identifier";
import type { Pos, Position } from "../util/location";
import * as charCodes from "charcodes";
@ -1997,8 +2000,8 @@ export default class ExpressionParser extends LValParser {
): void {
if (
this.state.strict &&
(reservedWords.strict(word) ||
(isBinding && reservedWords.strictBind(word)))
(isStrictReservedWord(word) ||
(isBinding && isStrictBindReservedWord(word)))
) {
this.raise(startLoc, word + " is a reserved word in strict mode");
}

View File

@ -4,28 +4,72 @@
import * as charCodes from "charcodes";
function makePredicate(words: string): (str: string) => boolean {
const wordsArr = words.split(" ");
return function(str) {
return wordsArr.indexOf(str) >= 0;
export const isES2015ReservedWord = (word: string): boolean => {
return word === "enum" || word === "await";
};
const reservedWordsStrict = new Set([
"implements",
"interface",
"let",
"package",
"private",
"protected",
"public",
"static",
"yield",
]);
export function isStrictReservedWord(word: string): boolean {
return reservedWordsStrict.has(word);
}
// Reserved word lists for various dialects of the language
export function isStrictBindReservedWord(word: string): boolean {
return word === "eval" || word === "arguments";
}
export const reservedWords = {
"6": makePredicate("enum await"),
strict: makePredicate(
"implements interface let package private protected public static yield",
),
strictBind: makePredicate("eval arguments"),
};
const keywords = new Set([
"break",
"case",
"catch",
"continue",
"debugger",
"default",
"do",
"else",
"finally",
"for",
"function",
"if",
"return",
"switch",
"throw",
"try",
"var",
"while",
"with",
"null",
"true",
"false",
"instanceof",
"typeof",
"void",
"delete",
"new",
"in",
"this",
"let",
"const",
"class",
"extends",
"export",
"import",
"yield",
"super",
]);
// And the keywords
export const isKeyword = makePredicate(
"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this let const class extends export import yield super",
);
export function isKeyword(word: string): boolean {
return keywords.has(word);
}
// ## Character categories

View File

@ -0,0 +1,18 @@
import { isKeyword } from "../../../src/util/identifier";
describe("identifier", () => {
describe("isKeyword", () => {
it("break is a keyword", () => {
expect(isKeyword("break")).toBe(true);
});
it("let is a keyword", () => {
expect(isKeyword("let")).toBe(true);
});
it("super is a keyword", () => {
expect(isKeyword("super")).toBe(true);
});
it("abc is not a keyword", () => {
expect(isKeyword("abc")).toBe(false);
});
});
});