diff --git a/packages/babel-traverse/src/index.js b/packages/babel-traverse/src/index.js index fa0306e07c..da880632ad 100644 --- a/packages/babel-traverse/src/index.js +++ b/packages/babel-traverse/src/index.js @@ -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); diff --git a/packages/babel-traverse/src/path/context.js b/packages/babel-traverse/src/path/context.js index 47c8f831f4..4a8c54197b 100644 --- a/packages/babel-traverse/src/path/context.js +++ b/packages/babel-traverse/src/path/context.js @@ -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): 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; - this.skipKeys = {}; + 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; diff --git a/packages/babel-traverse/src/path/index.js b/packages/babel-traverse/src/path/index.js index a1be4f5d8d..e73cbde9d1 100644 --- a/packages/babel-traverse/src/path/index.js +++ b/packages/babel-traverse/src/path/index.js @@ -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; 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( diff --git a/packages/babel-traverse/src/path/removal.js b/packages/babel-traverse/src/path/removal.js index b4d1330b25..9ddf0a2014 100644 --- a/packages/babel-traverse/src/path/removal.js +++ b/packages/babel-traverse/src/path/removal.js @@ -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; }