perf: replace lookahead by lookaheadCharCode (#10371)
* perf: replace lookahead by lookaheadCharCode * fix: flow ignore * refactor: add nextTokenStart method * refactor: duplicated isNewLine code * refactor: remove lookahead usage from babylon core
This commit is contained in:
parent
bc0966a46f
commit
0856618ed5
@ -613,7 +613,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
} else if (this.match(tt.questionDot)) {
|
} else if (this.match(tt.questionDot)) {
|
||||||
this.expectPlugin("optionalChaining");
|
this.expectPlugin("optionalChaining");
|
||||||
state.optionalChainMember = true;
|
state.optionalChainMember = true;
|
||||||
if (noCalls && this.lookahead().type === tt.parenL) {
|
if (noCalls && this.lookaheadCharCode() === charCodes.leftParenthesis) {
|
||||||
state.stop = true;
|
state.stop = true;
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
isIdentifierStart,
|
isIdentifierStart,
|
||||||
keywordRelationalOperator,
|
keywordRelationalOperator,
|
||||||
} from "../util/identifier";
|
} from "../util/identifier";
|
||||||
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
|
import { lineBreak } from "../util/whitespace";
|
||||||
import * as charCodes from "charcodes";
|
import * as charCodes from "charcodes";
|
||||||
import {
|
import {
|
||||||
BIND_CLASS,
|
BIND_CLASS,
|
||||||
@ -105,10 +105,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
if (!this.isContextual("let")) {
|
if (!this.isContextual("let")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
skipWhiteSpace.lastIndex = this.state.pos;
|
const next = this.nextTokenStart();
|
||||||
const skip = skipWhiteSpace.exec(this.input);
|
|
||||||
// $FlowIgnore
|
|
||||||
const next = this.state.pos + skip[0].length;
|
|
||||||
const nextCh = this.input.charCodeAt(next);
|
const nextCh = this.input.charCodeAt(next);
|
||||||
// For ambiguous cases, determine if a LexicalDeclaration (or only a
|
// For ambiguous cases, determine if a LexicalDeclaration (or only a
|
||||||
// Statement) is allowed here. If context is not empty then only a Statement
|
// Statement) is allowed here. If context is not empty then only a Statement
|
||||||
@ -170,7 +167,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
case tt._for:
|
case tt._for:
|
||||||
return this.parseForStatement(node);
|
return this.parseForStatement(node);
|
||||||
case tt._function:
|
case tt._function:
|
||||||
if (this.lookahead().type === tt.dot) break;
|
if (this.lookaheadCharCode() === charCodes.dot) break;
|
||||||
if (context) {
|
if (context) {
|
||||||
if (this.state.strict) {
|
if (this.state.strict) {
|
||||||
this.raise(
|
this.raise(
|
||||||
@ -223,8 +220,11 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
return this.parseEmptyStatement(node);
|
return this.parseEmptyStatement(node);
|
||||||
case tt._export:
|
case tt._export:
|
||||||
case tt._import: {
|
case tt._import: {
|
||||||
const nextToken = this.lookahead();
|
const nextTokenCharCode = this.lookaheadCharCode();
|
||||||
if (nextToken.type === tt.parenL || nextToken.type === tt.dot) {
|
if (
|
||||||
|
nextTokenCharCode === charCodes.leftParenthesis ||
|
||||||
|
nextTokenCharCode === charCodes.dot
|
||||||
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1746,11 +1746,11 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
maybeParseExportDeclaration(node: N.Node): boolean {
|
maybeParseExportDeclaration(node: N.Node): boolean {
|
||||||
if (this.shouldParseExportDeclaration()) {
|
if (this.shouldParseExportDeclaration()) {
|
||||||
if (this.isContextual("async")) {
|
if (this.isContextual("async")) {
|
||||||
const next = this.lookahead();
|
const next = this.nextTokenStart();
|
||||||
|
|
||||||
// export async;
|
// export async;
|
||||||
if (next.type !== tt._function) {
|
if (!this.isUnparsedContextual(next, "function")) {
|
||||||
this.unexpected(next.start, `Unexpected token, expected "function"`);
|
this.unexpected(next, `Unexpected token, expected "function"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1765,21 +1765,10 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
|
|
||||||
isAsyncFunction(): boolean {
|
isAsyncFunction(): boolean {
|
||||||
if (!this.isContextual("async")) return false;
|
if (!this.isContextual("async")) return false;
|
||||||
|
const next = this.nextTokenStart();
|
||||||
const { pos } = this.state;
|
|
||||||
|
|
||||||
skipWhiteSpace.lastIndex = pos;
|
|
||||||
const skip = skipWhiteSpace.exec(this.input);
|
|
||||||
|
|
||||||
if (!skip || !skip.length) return false;
|
|
||||||
|
|
||||||
const next = pos + skip[0].length;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!lineBreak.test(this.input.slice(pos, next)) &&
|
!lineBreak.test(this.input.slice(this.state.pos, next)) &&
|
||||||
this.input.slice(next, next + 8) === "function" &&
|
this.isUnparsedContextual(next, "function")
|
||||||
(next + 8 === this.length ||
|
|
||||||
!isIdentifierChar(this.input.charCodeAt(next + 8)))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1841,10 +1830,10 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lookahead = this.lookahead();
|
const next = this.nextTokenStart();
|
||||||
return (
|
return (
|
||||||
lookahead.type === tt.comma ||
|
this.input.charCodeAt(next) === charCodes.comma ||
|
||||||
(lookahead.type === tt.name && lookahead.value === "from")
|
this.isUnparsedContextual(next, "from")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { types as tt, type TokenType } from "../tokenizer/types";
|
|||||||
import Tokenizer from "../tokenizer";
|
import Tokenizer from "../tokenizer";
|
||||||
import type { Node } from "../types";
|
import type { Node } from "../types";
|
||||||
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
|
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
|
||||||
|
import { isIdentifierChar } from "../util/identifier";
|
||||||
|
import * as charCodes from "charcodes";
|
||||||
|
|
||||||
const literal = /^('|")((?:\\?.)*?)\1/;
|
const literal = /^('|")((?:\\?.)*?)\1/;
|
||||||
|
|
||||||
@ -26,8 +28,15 @@ export default class UtilParser extends Tokenizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isLookaheadRelational(op: "<" | ">"): boolean {
|
isLookaheadRelational(op: "<" | ">"): boolean {
|
||||||
const l = this.lookahead();
|
const next = this.nextTokenStart();
|
||||||
return l.type === tt.relational && l.value === op;
|
if (this.input.charAt(next) === op) {
|
||||||
|
if (next + 1 === this.input.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const afterNext = this.input.charCodeAt(next + 1);
|
||||||
|
return afterNext !== op.charCodeAt(0) && afterNext !== charCodes.equalsTo;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@ -60,9 +69,18 @@ export default class UtilParser extends Tokenizer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUnparsedContextual(nameStart: number, name: string): boolean {
|
||||||
|
const nameEnd = nameStart + name.length;
|
||||||
|
return (
|
||||||
|
this.input.slice(nameStart, nameEnd) === name &&
|
||||||
|
(nameEnd === this.input.length ||
|
||||||
|
!isIdentifierChar(this.input.charCodeAt(nameEnd)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
isLookaheadContextual(name: string): boolean {
|
isLookaheadContextual(name: string): boolean {
|
||||||
const l = this.lookahead();
|
const next = this.nextTokenStart();
|
||||||
return l.type === tt.name && l.value === name;
|
return this.isUnparsedContextual(next, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consumes contextual keyword if possible.
|
// Consumes contextual keyword if possible.
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import {
|
|||||||
BIND_CLASS,
|
BIND_CLASS,
|
||||||
} from "../../util/scopeflags";
|
} from "../../util/scopeflags";
|
||||||
import TypeScriptScopeHandler from "./scope";
|
import TypeScriptScopeHandler from "./scope";
|
||||||
|
import * as charCodes from "charcodes";
|
||||||
|
|
||||||
type TsModifier =
|
type TsModifier =
|
||||||
| "readonly"
|
| "readonly"
|
||||||
@ -657,7 +658,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
: this.match(tt._null)
|
: this.match(tt._null)
|
||||||
? "TSNullKeyword"
|
? "TSNullKeyword"
|
||||||
: keywordTypeFromName(this.state.value);
|
: keywordTypeFromName(this.state.value);
|
||||||
if (type !== undefined && this.lookahead().type !== tt.dot) {
|
if (
|
||||||
|
type !== undefined &&
|
||||||
|
this.lookaheadCharCode() !== charCodes.dot
|
||||||
|
) {
|
||||||
const node: N.TsKeywordType = this.startNode();
|
const node: N.TsKeywordType = this.startNode();
|
||||||
this.next();
|
this.next();
|
||||||
return this.finishNode(node, type);
|
return this.finishNode(node, type);
|
||||||
@ -1203,7 +1207,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
tsIsExternalModuleReference(): boolean {
|
tsIsExternalModuleReference(): boolean {
|
||||||
return (
|
return (
|
||||||
this.isContextual("require") && this.lookahead().type === tt.parenL
|
this.isContextual("require") &&
|
||||||
|
this.lookaheadCharCode() === charCodes.leftParenthesis
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
lineBreakG,
|
lineBreakG,
|
||||||
isNewLine,
|
isNewLine,
|
||||||
isWhitespace,
|
isWhitespace,
|
||||||
|
skipWhiteSpace,
|
||||||
} from "../util/whitespace";
|
} from "../util/whitespace";
|
||||||
import State from "./state";
|
import State from "./state";
|
||||||
|
|
||||||
@ -168,6 +169,18 @@ export default class Tokenizer extends LocationParser {
|
|||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nextTokenStart(): number {
|
||||||
|
const thisTokEnd = this.state.pos;
|
||||||
|
skipWhiteSpace.lastIndex = thisTokEnd;
|
||||||
|
const skip = skipWhiteSpace.exec(this.input);
|
||||||
|
// $FlowIgnore: The skipWhiteSpace ensures to match any string
|
||||||
|
return thisTokEnd + skip[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
lookaheadCharCode(): number {
|
||||||
|
return this.input.charCodeAt(this.nextTokenStart());
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle strict mode. Re-reads the next number or string to please
|
// Toggle strict mode. Re-reads the next number or string to please
|
||||||
// pedantic tests (`"use strict"; 010;` should fail).
|
// pedantic tests (`"use strict"; 010;` should fail).
|
||||||
|
|
||||||
@ -267,13 +280,7 @@ export default class Tokenizer extends LocationParser {
|
|||||||
const startLoc = this.state.curPosition();
|
const startLoc = this.state.curPosition();
|
||||||
let ch = this.input.charCodeAt((this.state.pos += startSkip));
|
let ch = this.input.charCodeAt((this.state.pos += startSkip));
|
||||||
if (this.state.pos < this.length) {
|
if (this.state.pos < this.length) {
|
||||||
while (
|
while (!isNewLine(ch) && ++this.state.pos < this.length) {
|
||||||
ch !== charCodes.lineFeed &&
|
|
||||||
ch !== charCodes.carriageReturn &&
|
|
||||||
ch !== charCodes.lineSeparator &&
|
|
||||||
ch !== charCodes.paragraphSeparator &&
|
|
||||||
++this.state.pos < this.length
|
|
||||||
) {
|
|
||||||
ch = this.input.charCodeAt(this.state.pos);
|
ch = this.input.charCodeAt(this.state.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,13 +448,7 @@ export default class Tokenizer extends LocationParser {
|
|||||||
let ch = this.input.charCodeAt(this.state.pos);
|
let ch = this.input.charCodeAt(this.state.pos);
|
||||||
if (ch !== charCodes.exclamationMark) return false;
|
if (ch !== charCodes.exclamationMark) return false;
|
||||||
|
|
||||||
while (
|
while (!isNewLine(ch) && ++this.state.pos < this.length) {
|
||||||
ch !== charCodes.lineFeed &&
|
|
||||||
ch !== charCodes.carriageReturn &&
|
|
||||||
ch !== charCodes.lineSeparator &&
|
|
||||||
ch !== charCodes.paragraphSeparator &&
|
|
||||||
++this.state.pos < this.length
|
|
||||||
) {
|
|
||||||
ch = this.input.charCodeAt(this.state.pos);
|
ch = this.input.charCodeAt(this.state.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user