Traverse performance (#10480)
* perf: remove this.inList assignment * perf: convert NodePath.parentKey into accessor function * perf: compress shouldSkip/shouldStop/removed traverse flags * perf: lazy initialize this.skipKeys * perf: lazily initialize NodePath.data * add code comments before bit operations * remove unused typeAnnotation property # Conflicts: # packages/babel-traverse/src/path/index.js * early return when visitor keys are empty
This commit is contained in:
parent
e9c1bce50f
commit
b114486bc1
@ -31,6 +31,10 @@ export default function traverse(
|
||||
}
|
||||
}
|
||||
|
||||
if (!t.VISITOR_KEYS[parent.type]) {
|
||||
return;
|
||||
}
|
||||
|
||||
visitors.explode(opts);
|
||||
|
||||
traverse.node(parent, opts, scope, state, parentPath);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// This file contains methods responsible for maintaining a TraversalContext.
|
||||
|
||||
import traverse from "../index";
|
||||
import { SHOULD_SKIP, SHOULD_STOP } from "./index";
|
||||
|
||||
export function call(key): boolean {
|
||||
const opts = this.opts;
|
||||
@ -43,7 +44,8 @@ export function _call(fns?: Array<Function>): boolean {
|
||||
// node has been replaced, it will have been requeued
|
||||
if (this.node !== node) return true;
|
||||
|
||||
if (this.shouldStop || this.shouldSkip || this.removed) return true;
|
||||
// this.shouldSkip || this.shouldStop || this.removed
|
||||
if (this._traverseFlags > 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -97,12 +99,15 @@ export function skip() {
|
||||
}
|
||||
|
||||
export function skipKey(key) {
|
||||
if (this.skipKeys == null) {
|
||||
this.skipKeys = {};
|
||||
}
|
||||
this.skipKeys[key] = true;
|
||||
}
|
||||
|
||||
export function stop() {
|
||||
this.shouldStop = true;
|
||||
this.shouldSkip = true;
|
||||
// this.shouldSkip = true; this.shouldStop = true;
|
||||
this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;
|
||||
}
|
||||
|
||||
export function setScope() {
|
||||
@ -122,10 +127,11 @@ export function setScope() {
|
||||
}
|
||||
|
||||
export function setContext(context) {
|
||||
this.shouldSkip = false;
|
||||
this.shouldStop = false;
|
||||
this.removed = false;
|
||||
if (this.skipKeys != null) {
|
||||
this.skipKeys = {};
|
||||
}
|
||||
// this.shouldSkip = false; this.shouldStop = false; this.removed = false;
|
||||
this._traverseFlags = 0;
|
||||
|
||||
if (context) {
|
||||
this.context = context;
|
||||
@ -220,9 +226,7 @@ export function pushContext(context) {
|
||||
}
|
||||
|
||||
export function setup(parentPath, container, listKey, key) {
|
||||
this.inList = !!listKey;
|
||||
this.listKey = listKey;
|
||||
this.parentKey = listKey || key;
|
||||
this.container = container;
|
||||
|
||||
this.parentPath = parentPath || this.parentPath;
|
||||
|
||||
@ -23,15 +23,18 @@ import * as NodePath_comments from "./comments";
|
||||
|
||||
const debug = buildDebug("babel");
|
||||
|
||||
export const REMOVED = 1 << 0;
|
||||
export const SHOULD_STOP = 1 << 1;
|
||||
export const SHOULD_SKIP = 1 << 2;
|
||||
|
||||
export default class NodePath {
|
||||
constructor(hub: HubInterface, parent: Object) {
|
||||
this.parent = parent;
|
||||
this.hub = hub;
|
||||
this.contexts = [];
|
||||
this.data = Object.create(null);
|
||||
this.shouldSkip = false;
|
||||
this.shouldStop = false;
|
||||
this.removed = false;
|
||||
this.data = null;
|
||||
// this.shouldSkip = false; this.shouldStop = false; this.removed = false;
|
||||
this._traverseFlags = 0;
|
||||
this.state = null;
|
||||
this.opts = null;
|
||||
this.skipKeys = null;
|
||||
@ -39,13 +42,10 @@ export default class NodePath {
|
||||
this.context = null;
|
||||
this.container = null;
|
||||
this.listKey = null;
|
||||
this.inList = false;
|
||||
this.parentKey = null;
|
||||
this.key = null;
|
||||
this.node = null;
|
||||
this.scope = null;
|
||||
this.type = null;
|
||||
this.typeAnnotation = null;
|
||||
}
|
||||
|
||||
parent: Object;
|
||||
@ -57,18 +57,16 @@ export default class NodePath {
|
||||
removed: boolean;
|
||||
state: any;
|
||||
opts: ?Object;
|
||||
_traverseFlags: number;
|
||||
skipKeys: ?Object;
|
||||
parentPath: ?NodePath;
|
||||
context: TraversalContext;
|
||||
container: ?Object | Array<Object>;
|
||||
listKey: ?string;
|
||||
inList: boolean;
|
||||
parentKey: ?string;
|
||||
key: ?string;
|
||||
node: ?Object;
|
||||
scope: Scope;
|
||||
type: ?string;
|
||||
typeAnnotation: ?Object;
|
||||
|
||||
static get({ hub, parentPath, parent, container, listKey, key }): NodePath {
|
||||
if (!hub && parentPath) {
|
||||
@ -111,10 +109,16 @@ export default class NodePath {
|
||||
}
|
||||
|
||||
setData(key: string, val: any): any {
|
||||
if (this.data == null) {
|
||||
this.data = Object.create(null);
|
||||
}
|
||||
return (this.data[key] = val);
|
||||
}
|
||||
|
||||
getData(key: string, def?: any): any {
|
||||
if (this.data == null) {
|
||||
this.data = Object.create(null);
|
||||
}
|
||||
let val = this.data[key];
|
||||
if (val === undefined && def !== undefined) val = this.data[key] = def;
|
||||
return val;
|
||||
@ -152,6 +156,49 @@ export default class NodePath {
|
||||
toString() {
|
||||
return generator(this.node).code;
|
||||
}
|
||||
|
||||
get inList() {
|
||||
return !!this.listKey;
|
||||
}
|
||||
|
||||
get parentKey() {
|
||||
return this.listKey || this.key;
|
||||
}
|
||||
|
||||
get shouldSkip() {
|
||||
return !!(this._traverseFlags & SHOULD_SKIP);
|
||||
}
|
||||
|
||||
set shouldSkip(v) {
|
||||
if (v) {
|
||||
this._traverseFlags |= SHOULD_SKIP;
|
||||
} else {
|
||||
this._traverseFlags &= ~SHOULD_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
get shouldStop() {
|
||||
return !!(this._traverseFlags & SHOULD_STOP);
|
||||
}
|
||||
|
||||
set shouldStop(v) {
|
||||
if (v) {
|
||||
this._traverseFlags |= SHOULD_STOP;
|
||||
} else {
|
||||
this._traverseFlags &= ~SHOULD_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
get removed() {
|
||||
return !!(this._traverseFlags & REMOVED);
|
||||
}
|
||||
set removed(v) {
|
||||
if (v) {
|
||||
this._traverseFlags |= REMOVED;
|
||||
} else {
|
||||
this._traverseFlags &= ~REMOVED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// This file contains methods responsible for removing a node.
|
||||
|
||||
import { hooks } from "./lib/removal-hooks";
|
||||
import { REMOVED, SHOULD_SKIP } from "./index";
|
||||
|
||||
export function remove() {
|
||||
this._assertUnremoved();
|
||||
@ -39,8 +40,8 @@ export function _remove() {
|
||||
}
|
||||
|
||||
export function _markRemoved() {
|
||||
this.shouldSkip = true;
|
||||
this.removed = true;
|
||||
// this.shouldSkip = true; this.removed = true;
|
||||
this._traverseFlags |= SHOULD_SKIP | REMOVED;
|
||||
this.node = null;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user