Skip to content

Commit

Permalink
perf: replace generic __clone by specific methods
Browse files Browse the repository at this point in the history
baseline 256 length-1 named export: 4_704 ops/sec ±1.59% (0.213ms)
baseline 512 length-1 named export: 2_426 ops/sec ±0.52% (0.412ms)
baseline 1024 length-1 named export: 1_118 ops/sec ±1.23% (0.895ms)
baseline 2048 length-1 named export: 556 ops/sec ±0.77% (1.799ms)
current 256 length-1 named export: 7_073 ops/sec ±33.67% (0.141ms)
current 512 length-1 named export: 4_441 ops/sec ±0.79% (0.225ms)
current 1024 length-1 named export: 2_142 ops/sec ±1.09% (0.467ms)
current 2048 length-1 named export: 943 ops/sec ±2.12% (1.06ms)
  • Loading branch information
JLHwung committed Jul 28, 2021
1 parent 0f9fafe commit 760023d
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 11 deletions.
7 changes: 4 additions & 3 deletions packages/babel-parser/src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
import { Errors, SourceTypeModuleErrors } from "./error";
import type { ParsingError } from "./error";
import { setInnerComments } from "./comments";
import { cloneIdentifier } from "./node";

/*::
import type { SourceType } from "../options";
Expand Down Expand Up @@ -1938,7 +1939,7 @@ export default class ExpressionParser extends LValParser {
prop.value = this.parseMaybeDefault(
startPos,
startLoc,
prop.key.__clone(),
cloneIdentifier(prop.key),
);
} else if (this.match(tt.eq) && refExpressionErrors) {
if (refExpressionErrors.shorthandAssign === -1) {
Expand All @@ -1947,10 +1948,10 @@ export default class ExpressionParser extends LValParser {
prop.value = this.parseMaybeDefault(
startPos,
startLoc,
prop.key.__clone(),
cloneIdentifier(prop.key),
);
} else {
prop.value = prop.key.__clone();
prop.value = cloneIdentifier(prop.key);
}
prop.shorthand = true;

Expand Down
41 changes: 41 additions & 0 deletions packages/babel-parser/src/parser/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Node implements NodeBase {
innerComments: Array<Comment>;
extra: { [key: string]: any };

// todo(Babel 8): remove this method in Babel 8
__clone(): this {
// $FlowIgnore
const newNode: any = new Node();
Expand All @@ -47,6 +48,46 @@ class Node implements NodeBase {
return newNode;
}
}
const NodePrototype = Node.prototype;

function clonePlaceholder(node: any): any {
return cloneIdentifier(node);
}

export function cloneIdentifier(node: any): any {
// We don't need to clone `typeAnnotations` and `optional`: because
// cloneIdentifier is only used in object shorthand and named import/export.
// Neither of them allow type annotations after the identifier or optional identifier
const { type, start, end, loc, range, extra, name } = node;
const cloned = Object.create(NodePrototype);
cloned.type = type;
cloned.start = start;
cloned.end = end;
cloned.loc = loc;
cloned.range = range;
cloned.extra = extra;
cloned.name = name;
if (type === "Placeholder") {
cloned.expectedNode = node.expectedNode;
}
return cloned;
}

export function cloneStringLiteral(node: any): any {
const { type, start, end, loc, range, extra } = node;
if (type === "Placeholder") {
return clonePlaceholder(node);
}
const cloned = Object.create(NodePrototype);
cloned.type = "StringLiteral";
cloned.start = start;
cloned.end = end;
cloned.loc = loc;
cloned.range = range;
cloned.extra = extra;
cloned.value = node.value;
return cloned;
}

export class NodeUtils extends UtilParser {
startNode<T: NodeType>(): T {
Expand Down
17 changes: 12 additions & 5 deletions packages/babel-parser/src/parser/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
import type { SourceType } from "../options";
import { Token } from "../tokenizer";
import { Position } from "../util/location";
import { cloneStringLiteral, cloneIdentifier } from "./node";

const loopLabel = { kind: "loop" },
switchLabel = { kind: "switch" };
Expand Down Expand Up @@ -2144,10 +2145,16 @@ export default class StatementParser extends ExpressionParser {
}

const node = this.startNode();
node.local = this.parseModuleExportName();
node.exported = this.eatContextual("as")
? this.parseModuleExportName()
: node.local.__clone();
const isString = this.match(tt.string);
const local = this.parseModuleExportName();
node.local = local;
if (this.eatContextual("as")) {
node.exported = this.parseModuleExportName();
} else if (isString) {
node.exported = cloneStringLiteral(local);
} else {
node.exported = cloneIdentifier(local);
}
nodes.push(this.finishNode(node, "ExportSpecifier"));
}

Expand Down Expand Up @@ -2423,7 +2430,7 @@ export default class StatementParser extends ExpressionParser {
);
}
this.checkReservedWord(imported.name, specifier.start, true, true);
specifier.local = imported.__clone();
specifier.local = cloneIdentifier(imported);
}
this.checkLVal(specifier.local, "import specifier", BIND_LEXICAL);
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
Expand Down
7 changes: 4 additions & 3 deletions packages/babel-parser/src/plugins/flow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from "../../util/scopeflags";
import type { ExpressionErrors } from "../../parser/util";
import { Errors, makeErrorTemplates, ErrorCodes } from "../../parser/error";
import { cloneIdentifier } from "../../parser/node";

const reservedTypes = new Set([
"_",
Expand Down Expand Up @@ -2655,7 +2656,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// `import {type as ,` or `import {type as }`
specifier.imported = as_ident;
specifier.importKind = specifierTypeKind;
specifier.local = as_ident.__clone();
specifier.local = cloneIdentifier(as_ident);
} else {
// `import {type as foo`
specifier.imported = firstIdent;
Expand All @@ -2673,7 +2674,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
specifier.local = this.parseIdentifier();
} else {
isBinding = true;
specifier.local = specifier.imported.__clone();
specifier.local = cloneIdentifier(specifier.imported);
}
} else {
if (firstIdentIsString) {
Expand All @@ -2688,7 +2689,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isBinding = true;
specifier.imported = firstIdent;
specifier.importKind = null;
specifier.local = specifier.imported.__clone();
specifier.local = cloneIdentifier(specifier.imported);
}

const nodeIsTypeImport = hasTypeImportKind(node);
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export type Identifier = PatternBase & {
type: "Identifier",
name: string,

// @deprecated
__clone(): Identifier,

// TypeScript only. Used in case of an optional parameter.
Expand Down

0 comments on commit 760023d

Please sign in to comment.