Improve performance by removing all spread/rest usages (#561)

This commit is contained in:
Daniel Tschinder 2017-06-05 19:21:41 +02:00 committed by GitHub
parent bbc3cd45cf
commit 775dcfa6d6
4 changed files with 104 additions and 43 deletions

View File

@ -753,7 +753,6 @@ export default class ExpressionParser extends LValParser {
const elem = this.startNode();
if (this.state.value === null) {
if (!isTagged) {
// $FlowFixMe
this.raise(this.state.invalidTemplateEscapePosition, "Invalid escape sequence in template");
} else {
this.state.invalidTemplateEscapePosition = null;

View File

@ -1046,7 +1046,7 @@ export default class StatementParser extends ExpressionParser {
// Parses a comma-separated list of module exports.
parseExportSpecifiers(): $ReadOnlyArray<N.ExportSpecifier> {
parseExportSpecifiers(): Array<N.ExportSpecifier> {
const nodes = [];
let first = true;
let needsFrom;

View File

@ -1,8 +1,9 @@
// @flow
import { types as tt } from "../tokenizer/types";
import { types as tt, TokenType } from "../tokenizer/types";
import type Parser from "../parser";
import * as N from "../types";
import type { Pos, Position } from "../util/location";
function isSimpleProperty(node: N.Node): boolean {
return node != null &&
@ -73,7 +74,11 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
checkLVal(
expr: N.Expression, isBinding: ?boolean, checkClashes: ?{ [key: string]: boolean }, ...args): void {
expr: N.Expression,
isBinding: ?boolean,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string
): void {
switch (expr.type) {
case "ObjectPattern":
expr.properties.forEach((prop) => {
@ -86,7 +91,7 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
});
break;
default:
super.checkLVal(expr, isBinding, checkClashes, ...args);
super.checkLVal(expr, isBinding, checkClashes, contextDescription);
}
}
@ -136,23 +141,30 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return directive;
}
parseBlockBody(node: N.BlockStatementLike, ...args): void {
super.parseBlockBody(node, ...args);
parseBlockBody(
node: N.BlockStatementLike,
allowDirectives: ?boolean,
topLevel: boolean,
end: TokenType
): void {
super.parseBlockBody(node, allowDirectives, topLevel, end);
const directiveStatements = node.directives.map((d) => this.directiveToStmt(d));
node.body = directiveStatements.concat(node.body);
delete node.directives;
}
parseClassMethod(classBody: N.ClassBody, ...args) {
super.parseClassMethod(classBody, ...args);
const body = classBody.body;
// $FlowIgnore
body[body.length - 1].type = "MethodDefinition";
parseClassMethod(
classBody: N.ClassBody,
method: N.ClassMethod,
isGenerator: boolean,
isAsync: boolean
): void {
this.parseMethod(method, isGenerator, isAsync);
classBody.body.push(this.finishNode(method, "MethodDefinition"));
}
parseExprAtom(...args): N.Expression {
parseExprAtom(refShorthandDefaultPos?: ?Pos): N.Expression {
switch (this.state.type) {
case tt.regexp:
return this.estreeParseRegExpLiteral(this.state.value);
@ -171,22 +183,31 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return this.estreeParseLiteral(false);
default:
return super.parseExprAtom(...args);
return super.parseExprAtom(refShorthandDefaultPos);
}
}
parseLiteral<T : N.Literal>(...args): T {
const node = super.parseLiteral(...args);
parseLiteral<T : N.Literal>(
value: any,
type: /*T["kind"]*/string,
startPos?: number,
startLoc?: Position
): T {
const node = super.parseLiteral(value, type, startPos, startLoc);
node.raw = node.extra.raw;
delete node.extra;
return node;
}
parseMethod(node: N.MethodLike, ...args): N.MethodLike {
parseMethod(
node: N.MethodLike,
isGenerator?: boolean,
isAsync?: boolean
): N.MethodLike {
let funcNode = this.startNode();
funcNode.kind = node.kind; // provide kind, so super method correctly sets state
funcNode = super.parseMethod(funcNode, ...args);
funcNode = super.parseMethod(funcNode, isGenerator, isAsync);
delete funcNode.kind;
// $FlowIgnore
node.value = this.finishNode(funcNode, "FunctionExpression");
@ -194,8 +215,13 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return node;
}
parseObjectMethod(...args): ?N.ObjectMethod {
const node = super.parseObjectMethod(...args);
parseObjectMethod(
prop: N.ObjectMethod,
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean
): ?N.ObjectMethod {
const node = super.parseObjectMethod(prop, isGenerator, isAsync, isPattern);
if (node) {
// $FlowIgnore
@ -207,8 +233,14 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return node;
}
parseObjectProperty(...args): ?N.ObjectProperty {
const node = super.parseObjectProperty(...args);
parseObjectProperty(
prop: N.ObjectProperty,
startPos: ?number,
startLoc: ?Position,
isPattern: boolean,
refShorthandDefaultPos: ?Pos
): ?N.ObjectProperty {
const node = super.parseObjectProperty(prop, startPos, startLoc, isPattern, refShorthandDefaultPos);
if (node) {
// $FlowIgnore
@ -220,9 +252,13 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return node;
}
toAssignable(node: N.Node, isBinding: ?boolean, ...args): N.Node {
toAssignable(
node: N.Node,
isBinding: ?boolean,
contextDescription: string
): N.Node {
if (isSimpleProperty(node)) {
this.toAssignable(node.value, isBinding, ...args);
this.toAssignable(node.value, isBinding, contextDescription);
return node;
} else if (node.type === "ObjectExpression") {
@ -240,6 +276,6 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return node;
}
return super.toAssignable(node, isBinding, ...args);
return super.toAssignable(node, isBinding, contextDescription);
}
};

View File

@ -1145,8 +1145,8 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
}
parseClassId(node: N.Class, ...args) {
super.parseClassId(node, ...args);
parseClassId(node: N.Class, isStatement: boolean, optionalId: ?boolean) {
super.parseClassId(node, isStatement, optionalId);
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
}
@ -1205,9 +1205,9 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
// parse an item inside a expression list eg. `(NODE, NODE)` where NODE represents
// the position where this function is called
parseExprListItem(...args): ?N.Expression {
parseExprListItem(allowEmpty: ?boolean, refShorthandDefaultPos: ?Pos, refNeedsArrowPos: ?Pos): ?N.Expression {
const container = this.startNode();
const node = super.parseExprListItem(...args);
const node = super.parseExprListItem(allowEmpty, refShorthandDefaultPos, refNeedsArrowPos);
if (this.match(tt.colon)) {
container._exprListItem = true;
container.expression = node;
@ -1218,9 +1218,14 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
}
checkLVal(node: N.Expression, ...args): void {
if (node.type !== "TypeCastExpression") {
return super.checkLVal(node, ...args);
checkLVal(
expr: N.Expression,
isBinding: ?boolean,
checkClashes: ?{ [key: string]: boolean },
contextDescription: string
): void {
if (expr.type !== "TypeCastExpression") {
return super.checkLVal(expr, isBinding, checkClashes, contextDescription);
}
}
@ -1247,7 +1252,12 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
// parse type parameters for class methods
parseClassMethod(classBody: N.ClassBody, method: N.ClassMethod, ...args): void {
parseClassMethod(
classBody: N.ClassBody,
method: N.ClassMethod,
isGenerator: boolean,
isAsync: boolean
): void {
if (method.variance) {
this.unexpected(method.variance.start);
}
@ -1256,7 +1266,7 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
method.typeParameters = this.flowParseTypeParameterDeclaration();
}
super.parseClassMethod(classBody, method, ...args);
super.parseClassMethod(classBody, method, isGenerator, isAsync);
}
// parse a the super class type parameters and implements
@ -1290,7 +1300,15 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
// parse type parameters for object method shorthand
parseObjPropValue(prop: N.ObjectMember, ...args): void {
parseObjPropValue(
prop: N.ObjectMember,
startPos: ?number,
startLoc: ?Position,
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean,
refShorthandDefaultPos: ?Pos
): void {
if (prop.variance) {
this.unexpected(prop.variance.start);
}
@ -1304,7 +1322,15 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
if (!this.match(tt.parenL)) this.unexpected();
}
super.parseObjPropValue(prop, ...args);
super.parseObjPropValue(
prop,
startPos,
startLoc,
isGenerator,
isAsync,
isPattern,
refShorthandDefaultPos
);
// add typeParameters if we found them
if (typeParameters) {
@ -1324,8 +1350,8 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
return param;
}
parseMaybeDefault(...args): N.Pattern {
const node = super.parseMaybeDefault(...args);
parseMaybeDefault(startPos?: ?number, startLoc?: ?Position, left?: ?N.Pattern): N.Pattern {
const node = super.parseMaybeDefault(startPos, startLoc, left);
if (node.type === "AssignmentPattern" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) {
this.raise(node.typeAnnotation.start, "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`");
@ -1456,12 +1482,12 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
// parse the rest, make sure the rest is an arrow function, and go from
// there
// 3. This is neither. Just call the super method
parseMaybeAssign(...args): N.Expression {
parseMaybeAssign(noIn?: ?boolean, refShorthandDefaultPos?: ?Pos, afterLeftParse?: Function, refNeedsArrowPos?: ?Pos): N.Expression {
let jsxError = null;
if (tt.jsxTagStart && this.match(tt.jsxTagStart)) {
const state = this.state.clone();
try {
return super.parseMaybeAssign(...args);
return super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos);
} catch (err) {
if (err instanceof SyntaxError) {
this.state = state;
@ -1485,7 +1511,7 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
try {
typeParameters = this.flowParseTypeParameterDeclaration();
arrowExpression = super.parseMaybeAssign(...args);
arrowExpression = super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos);
arrowExpression.typeParameters = typeParameters;
this.resetStartLocationFromNode(arrowExpression, typeParameters);
} catch (err) {
@ -1504,7 +1530,7 @@ export default (superClass: Class<Parser>): Class<Parser> => class extends super
}
}
return super.parseMaybeAssign(...args);
return super.parseMaybeAssign(noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos);
}
// handle return types for arrow functions