Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser Performance Collection #9348

Merged
merged 21 commits into from Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion babel.config.js
Expand Up @@ -14,12 +14,16 @@ module.exports = function(api) {
let convertESM = true;
let ignoreLib = true;
let includeRuntime = false;
const nodeVersion = "6.9";

switch (env) {
// Configs used during bundling builds.
case "babel-parser":
convertESM = false;
ignoreLib = false;
envOpts.targets = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible we didn't add this before since Babylon was in another repo and a different config? Or I think it was actually slower before? Or it was because of browser support..

node: nodeVersion,
};
break;
case "standalone":
convertESM = false;
Expand All @@ -29,7 +33,7 @@ module.exports = function(api) {
case "production":
// Config during builds before publish.
envOpts.targets = {
node: "6.9",
node: nodeVersion,
};
break;
case "development":
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/package.json
Expand Up @@ -30,7 +30,7 @@
"devDependencies": {
"@babel/helper-fixtures": "^7.2.0",
"charcodes": "0.1.0",
"unicode-11.0.0": "^0.7.7"
"unicode-11.0.0": "^0.7.8"
},
"bin": {
"parser": "./bin/babel-parser.js"
Expand Down
4 changes: 4 additions & 0 deletions packages/babel-parser/scripts/generate-identifier-regex.js
Expand Up @@ -60,11 +60,15 @@ function generate(chars) {
const startData = generate(start);
const contData = generate(cont);

console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierStartChars = "' + startData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierChars = "' + contData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"
);
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"
);
10 changes: 5 additions & 5 deletions packages/babel-parser/src/parser/base.js
@@ -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";
Expand All @@ -16,21 +16,21 @@ export default class BaseParser {

// Initialized by Tokenizer
state: State;
input: string;

isReservedWord(word: string): boolean {
if (word === "await") {
return this.inModule;
} else {
return reservedWords[6](word);
return isES2015ReservedWord(word);
}
}

hasPlugin(name: string): boolean {
return Object.hasOwnProperty.call(this.plugins, name);
return this.plugins.has(name);
}

getPluginOption(plugin: string, name: string) {
if (this.hasPlugin(plugin)) return this.plugins[plugin][name];
// $FlowIssue
if (this.hasPlugin(plugin)) return this.plugins.get(plugin)[name];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, what does flow complain about here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is because of this: facebook/flow#2751
Flow does not realize that calling has ensures that get will return something !=null
Other way would be just calling get and testing if != null.

}
}
36 changes: 23 additions & 13 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -21,7 +21,11 @@
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,
isKeyword,
} from "../util/identifier";
import type { Pos, Position } from "../util/location";
import * as charCodes from "charcodes";

Expand Down Expand Up @@ -525,7 +529,7 @@ export default class ExpressionParser extends LValParser {
} else if (this.match(tt.questionDot)) {
this.expectPlugin("optionalChaining");
state.optionalChainMember = true;
if (noCalls && this.lookahead().type == tt.parenL) {
if (noCalls && this.lookahead().type === tt.parenL) {
state.stop = true;
return base;
}
Expand Down Expand Up @@ -869,9 +873,9 @@ export default class ExpressionParser extends LValParser {
return this.parseFunction(node, false, false, true);
} else if (
canBeArrow &&
!this.canInsertSemicolon() &&
id.name === "async" &&
this.match(tt.name)
this.match(tt.name) &&
!this.canInsertSemicolon()
) {
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
const oldInAsync = this.state.inAsync;
Expand All @@ -886,7 +890,8 @@ export default class ExpressionParser extends LValParser {
return node;
}

if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) {
this.next();
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
this.parseArrowExpression(node, [id]);
Expand Down Expand Up @@ -1146,7 +1151,11 @@ export default class ExpressionParser extends LValParser {

const node = this.startNodeAt(startPos, startLoc);
this.addExtra(node, "rawValue", value);
this.addExtra(node, "raw", this.input.slice(startPos, this.state.end));
this.addExtra(
node,
"raw",
this.state.input.slice(startPos, this.state.end),
);
node.value = value;
this.next();
return this.finishNode(node, type);
Expand Down Expand Up @@ -1365,7 +1374,7 @@ export default class ExpressionParser extends LValParser {
}
}
elem.value = {
raw: this.input
raw: this.state.input
.slice(this.state.start, this.state.end)
.replace(/\r\n?/g, "\n"),
cooked: this.state.value,
Expand Down Expand Up @@ -1967,7 +1976,8 @@ export default class ExpressionParser extends LValParser {
if (
(name === "class" || name === "function") &&
(this.state.lastTokEnd !== this.state.lastTokStart + 1 ||
this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot)
this.state.input.charCodeAt(this.state.lastTokStart) !==
charCodes.dot)
) {
this.state.context.pop();
}
Expand All @@ -1991,8 +2001,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");
}
Expand All @@ -2011,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");
}
}
Expand Down Expand Up @@ -2071,8 +2081,8 @@ export default class ExpressionParser extends LValParser {
this.next();
if (
this.match(tt.semi) ||
this.canInsertSemicolon() ||
(!this.match(tt.star) && !this.state.type.startsExpr)
(!this.match(tt.star) && !this.state.type.startsExpr) ||
this.canInsertSemicolon()
) {
node.delegate = false;
node.argument = null;
Expand Down
11 changes: 4 additions & 7 deletions packages/babel-parser/src/parser/index.js
Expand Up @@ -6,9 +6,7 @@ import type { PluginList } from "../plugin-utils";
import { getOptions } from "../options";
import StatementParser from "./statement";

export type PluginsMap = {
[key: string]: { [option: string]: any },
};
export type PluginsMap = Map<string, { [string]: any }>;

export default class Parser extends StatementParser {
// Forward-declaration so typescript plugin can override jsx plugin
Expand All @@ -22,7 +20,6 @@ export default class Parser extends StatementParser {

this.options = options;
this.inModule = this.options.sourceType === "module";
this.input = input;
this.plugins = pluginsMap(this.options.plugins);
this.filename = options.sourceFilename;
}
Expand All @@ -36,10 +33,10 @@ export default class Parser extends StatementParser {
}

function pluginsMap(plugins: PluginList): PluginsMap {
const pluginMap: PluginsMap = (Object.create(null): Object);
const pluginMap: PluginsMap = new Map();
for (const plugin of plugins) {
const [name, options = {}] = Array.isArray(plugin) ? plugin : [plugin, {}];
if (!pluginMap[name]) pluginMap[name] = options || {};
const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];
if (!pluginMap.has(name)) pluginMap.set(name, options || {});
}
return pluginMap;
}
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/location.js
Expand Up @@ -21,7 +21,7 @@ export default class LocationParser extends CommentsParser {
code?: string,
} = {},
): empty {
const loc = getLineInfo(this.input, pos);
const loc = getLineInfo(this.state.input, pos);
message += ` (${loc.line}:${loc.column})`;
// $FlowIgnore
const err: SyntaxError & { pos: number, loc: Position } = new SyntaxError(
Expand Down
31 changes: 16 additions & 15 deletions packages/babel-parser/src/parser/lval.js
Expand Up @@ -56,9 +56,13 @@ export default class LValParser extends NodeUtils {

case "ObjectExpression":
node.type = "ObjectPattern";
for (let index = 0; index < node.properties.length; index++) {
const prop = node.properties[index];
const isLast = index === node.properties.length - 1;
for (
let i = 0, length = node.properties.length, last = length - 1;
i < length;
i++
) {
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isBinding, isLast);
}
break;
Expand Down Expand Up @@ -145,12 +149,10 @@ export default class LValParser extends NodeUtils {
const arg = last.argument;
this.toAssignable(arg, isBinding, contextDescription);
if (
[
"Identifier",
"MemberExpression",
"ArrayPattern",
"ObjectPattern",
].indexOf(arg.type) === -1
arg.type !== "Identifier" &&
arg.type !== "MemberExpression" &&
arg.type !== "ArrayPattern" &&
arg.type !== "ObjectPattern"
) {
this.unexpected(arg.start);
}
Expand Down Expand Up @@ -426,13 +428,12 @@ export default class LValParser extends NodeUtils {
}

checkToRestConversion(node: SpreadElement): void {
const validArgumentTypes = ["Identifier", "MemberExpression"];

if (validArgumentTypes.indexOf(node.argument.type) !== -1) {
return;
if (
node.argument.type !== "Identifier" &&
node.argument.type !== "MemberExpression"
) {
this.raise(node.argument.start, "Invalid rest operator's argument");
}

this.raise(node.argument.start, "Invalid rest operator's argument");
}

checkCommaAfterRest(close: TokenType, kind: string): void {
Expand Down
20 changes: 12 additions & 8 deletions packages/babel-parser/src/parser/node.js
Expand Up @@ -7,8 +7,6 @@ import type { Comment, Node as NodeType, NodeBase } from "../types";

// Start an AST node, attaching a start offset.

const commentKeys = ["leadingComments", "trailingComments", "innerComments"];

class Node implements NodeBase {
constructor(parser: Parser, pos: number, loc: Position) {
this.type = "";
Expand All @@ -31,16 +29,22 @@ class Node implements NodeBase {

__clone(): this {
// $FlowIgnore
const node2: any = new Node();
Object.keys(this).forEach(key => {
const newNode: any = new Node();
const keys = Object.keys(this);
for (let i = 0, length = keys.length; i < length; i++) {
const key = keys[i];
// Do not clone comments that are already attached to the node
if (commentKeys.indexOf(key) < 0) {
if (
key !== "leadingComments" &&
key !== "trailingComments" &&
key !== "innerComments"
) {
// $FlowIgnore
node2[key] = this[key];
newNode[key] = this[key];
}
});
}

return node2;
return newNode;
}
}

Expand Down