further develop ast paths that represent a single location in the ast as an abstraction around a node-parent relationship
This commit is contained in:
parent
7a6e568940
commit
f62a3ef394
@ -6,7 +6,7 @@ var visitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
// check if this node is a referenced identifier that matches the same as our
|
||||
// function id
|
||||
if (!t.isReferencedIdentifier(node, parent, { name: state.name })) return;
|
||||
if (!this.isReferencedIdentifier({ name: state.name })) return;
|
||||
|
||||
// check that we don't have a local variable declared as that removes the need
|
||||
// for the wrapper
|
||||
|
||||
@ -24,7 +24,7 @@ module.exports = function (node, callId, scope) {
|
||||
|
||||
var call = t.callExpression(callId, [node]);
|
||||
var id = node.id;
|
||||
delete node.id;
|
||||
node.id = null;
|
||||
|
||||
if (t.isFunctionDeclaration(node)) {
|
||||
var declar = t.variableDeclaration("let", [
|
||||
|
||||
@ -2,7 +2,7 @@ import t from "../../../types";
|
||||
|
||||
var visitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
if (!this.isReferencedIdentifier()) return;
|
||||
|
||||
var declared = state.letRefs[node.name];
|
||||
if (!declared) return;
|
||||
|
||||
@ -109,7 +109,7 @@ function traverseReplace(node, parent, scope, remaps) {
|
||||
|
||||
var letReferenceBlockVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isFunction(node)) {
|
||||
if (this.isFunction()) {
|
||||
scope.traverse(node, letReferenceFunctionVisitor, state);
|
||||
return this.skip();
|
||||
}
|
||||
@ -119,7 +119,7 @@ var letReferenceBlockVisitor = {
|
||||
var letReferenceFunctionVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
// not a direct reference
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
if (!this.isReferencedIdentifier()) return;
|
||||
|
||||
// this scope has a variable with the same name so it couldn't belong
|
||||
// to our let scope
|
||||
@ -134,17 +134,17 @@ var letReferenceFunctionVisitor = {
|
||||
|
||||
var hoistVarDeclarationsVisitor = {
|
||||
enter(node, parent, scope, self) {
|
||||
if (t.isForStatement(node)) {
|
||||
if (this.isForStatement()) {
|
||||
if (isVar(node.init, node)) {
|
||||
node.init = t.sequenceExpression(self.pushDeclar(node.init));
|
||||
}
|
||||
} else if (t.isFor(node)) {
|
||||
} else if (this.isFor()) {
|
||||
if (isVar(node.left, node)) {
|
||||
node.left = node.left.declarations[0].id;
|
||||
}
|
||||
} else if (isVar(node, parent)) {
|
||||
return self.pushDeclar(node).map(t.expressionStatement);
|
||||
} else if (t.isFunction(node)) {
|
||||
} else if (this.isFunction()) {
|
||||
return this.skip();
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,7 @@ var hoistVarDeclarationsVisitor = {
|
||||
|
||||
var loopLabelVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isLabeledStatement(node)) {
|
||||
if (this.isLabeledStatement()) {
|
||||
state.innerLabels.push(node.label.name);
|
||||
}
|
||||
}
|
||||
@ -170,13 +170,13 @@ var loopVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
var replace;
|
||||
|
||||
if (t.isLoop(node)) {
|
||||
if (this.isLoop()) {
|
||||
state.ignoreLabeless = true;
|
||||
scope.traverse(node, loopVisitor, state);
|
||||
state.ignoreLabeless = false;
|
||||
}
|
||||
|
||||
if (t.isFunction(node) || t.isLoop(node)) {
|
||||
if (this.isFunction() || this.isLoop()) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ var loopVisitor = {
|
||||
replace = t.literal(loopText);
|
||||
}
|
||||
|
||||
if (t.isReturnStatement(node)) {
|
||||
if (this.isReturnStatement()) {
|
||||
state.hasReturn = true;
|
||||
replace = t.objectExpression([
|
||||
t.property("init", t.identifier("v"), node.argument || t.identifier("undefined"))
|
||||
|
||||
@ -7,8 +7,8 @@ export function check(node) {
|
||||
|
||||
var visitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
if (this.isAssignmentExpression() || this.isUpdateExpression()) {
|
||||
var ids = this.getBindingIdentifiers();
|
||||
|
||||
for (var name in ids) {
|
||||
var id = ids[name];
|
||||
@ -30,7 +30,7 @@ var visitor = {
|
||||
|
||||
throw state.file.errorWithNode(id, messages.get("readOnly", name));
|
||||
}
|
||||
} else if (t.isScope(node, parent)) {
|
||||
} else if (this.isScope()) {
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ export function VariableDeclaration(node, parent, scope, file) {
|
||||
}
|
||||
|
||||
return nodes;
|
||||
};
|
||||
}
|
||||
|
||||
var hasRest = function (pattern) {
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
|
||||
@ -41,14 +41,14 @@ export function ForOfStatement(node, parent, scope, file) {
|
||||
|
||||
var breakVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isLoop(node)) {
|
||||
if (this.isLoop()) {
|
||||
state.ignoreLabeless = true;
|
||||
scope.traverse(node, breakVisitor, state);
|
||||
state.ignoreLabeless = false;
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
if (t.isBreakStatement(node)) {
|
||||
if (this.isBreakStatement()) {
|
||||
if (!node.label && state.ignoreLabeless) return;
|
||||
if (node.label && node.label.name !== state.label) return;
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ var hasDefaults = function (node) {
|
||||
|
||||
var iifeVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
if (!this.isReferencedIdentifier()) return;
|
||||
if (!state.scope.hasOwnBinding(node.name)) return;
|
||||
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
|
||||
|
||||
|
||||
@ -7,13 +7,13 @@ export var check = t.isRestElement;
|
||||
var memberExpressionOptimisationVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
// check if this scope has a local binding that will shadow the rest parameter
|
||||
if (t.isScope(node, parent) && !scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
|
||||
if (this.isScope() && !scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
// skip over functions as whatever `arguments` we reference inside will refer
|
||||
// to the wrong function
|
||||
if (t.isFunctionDeclaration(node) || t.isFunctionExpression(node)) {
|
||||
if (this.isFunctionDeclaration() || this.isFunctionExpression()) {
|
||||
state.noOptimise = true;
|
||||
scope.traverse(node, memberExpressionOptimisationVisitor, state);
|
||||
state.noOptimise = false;
|
||||
@ -21,7 +21,7 @@ var memberExpressionOptimisationVisitor = {
|
||||
}
|
||||
|
||||
// is this a referenced identifier and is it referencing the rest parameter?
|
||||
if (!t.isReferencedIdentifier(node, parent, { name: state.name })) return;
|
||||
if (!this.isReferencedIdentifier({ name: state.name })) return;
|
||||
|
||||
if (!state.noOptimise && t.isMemberExpression(parent) && parent.computed) {
|
||||
// if we know that this member expression is referencing a number then we can safely
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import clone from "lodash/lang/clone";
|
||||
import t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
@ -12,6 +11,6 @@ export function Property(node) {
|
||||
|
||||
if (node.shorthand) {
|
||||
node.shorthand = false;
|
||||
node.key = t.removeComments(clone(node.key));
|
||||
node.key = t.removeComments(t.clone(node.key));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ function returnBlock(expr) {
|
||||
// looks for and replaces tail recursion calls
|
||||
var firstPass = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isIfStatement(node)) {
|
||||
if (this.isIfStatement()) {
|
||||
if (t.isReturnStatement(node.alternate)) {
|
||||
t.ensureBlock(node, "alternate");
|
||||
}
|
||||
@ -25,7 +25,7 @@ var firstPass = {
|
||||
if (t.isReturnStatement(node.consequent)) {
|
||||
t.ensureBlock(node, "consequent");
|
||||
}
|
||||
} else if (t.isReturnStatement(node)) {
|
||||
} else if (this.isReturnStatement()) {
|
||||
this.skip();
|
||||
return state.subTransform(node.argument);
|
||||
} else if (t.isTryStatement(parent)) {
|
||||
@ -34,9 +34,9 @@ var firstPass = {
|
||||
} else if (parent.finalizer && node !== parent.finalizer) {
|
||||
this.skip();
|
||||
}
|
||||
} else if (t.isFunction(node)) {
|
||||
} else if (this.isFunction()) {
|
||||
this.skip();
|
||||
} else if (t.isVariableDeclaration(node)) {
|
||||
} else if (this.isVariableDeclaration()) {
|
||||
this.skip();
|
||||
state.vars.push(node);
|
||||
}
|
||||
@ -47,15 +47,15 @@ var firstPass = {
|
||||
// them as needed
|
||||
var secondPass = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isThisExpression(node)) {
|
||||
if (this.isThisExpression()) {
|
||||
state.needsThis = true;
|
||||
return state.getThisId();
|
||||
} else if (t.isReferencedIdentifier(node, parent, { name: "arguments" })) {
|
||||
} else if (this.isReferencedIdentifier({ name: "arguments" })) {
|
||||
state.needsArguments = true;
|
||||
return state.getArgumentsId();
|
||||
} else if (t.isFunction(node)) {
|
||||
} else if (this.isFunction()) {
|
||||
this.skip();
|
||||
if (t.isFunctionDeclaration(node)) {
|
||||
if (this.isFunctionDeclaration()) {
|
||||
node = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(node.id, t.toExpression(node))
|
||||
]);
|
||||
@ -69,7 +69,7 @@ var secondPass = {
|
||||
// optimizes recursion by removing `this` and `arguments` if they aren't used
|
||||
var thirdPass = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!t.isExpressionStatement(node)) return;
|
||||
if (!this.isExpressionStatement()) return;
|
||||
|
||||
var expr = node.expression;
|
||||
if (!t.isAssignmentExpression(expr)) return;
|
||||
|
||||
@ -2,7 +2,7 @@ import t from "../../../types";
|
||||
|
||||
var functionChildrenVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isFunction(node) && !node._aliasFunction) {
|
||||
if (this.isFunction() && !node._aliasFunction) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
@ -10,22 +10,22 @@ var functionChildrenVisitor = {
|
||||
|
||||
var getId;
|
||||
|
||||
if (t.isIdentifier(node) && node.name === "arguments") {
|
||||
if (this.isIdentifier() && node.name === "arguments") {
|
||||
getId = state.getArgumentsId;
|
||||
} else if (t.isThisExpression(node)) {
|
||||
} else if (this.isThisExpression()) {
|
||||
getId = state.getThisId;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isReferenced(node, parent)) return getId();
|
||||
if (this.isReferenced()) return getId();
|
||||
}
|
||||
};
|
||||
|
||||
var functionVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!node._aliasFunction) {
|
||||
if (t.isFunction(node)) {
|
||||
if (this.isFunction()) {
|
||||
// stop traversal of this node as it'll be hit again by this transformer
|
||||
return this.skip();
|
||||
} else {
|
||||
|
||||
@ -16,14 +16,15 @@ var ALIASABLE_CONSTRUCTORS = [
|
||||
"Map",
|
||||
"WeakMap",
|
||||
"Set",
|
||||
"WeakSet"
|
||||
"WeakSet",
|
||||
"Number"
|
||||
];
|
||||
|
||||
var astVisitor = {
|
||||
enter(node, parent, scope, file) {
|
||||
var prop;
|
||||
|
||||
if (t.isMemberExpression(node) && t.isReferenced(node, parent)) {
|
||||
if (this.isMemberExpression() && this.isReferenced()) {
|
||||
// Array.from -> _core.Array.from
|
||||
var obj = node.object;
|
||||
prop = node.property;
|
||||
@ -34,10 +35,10 @@ var astVisitor = {
|
||||
this.skip();
|
||||
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
|
||||
}
|
||||
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
|
||||
} else if (this.isReferencedIdentifier() && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
|
||||
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
|
||||
return t.memberExpression(file.get("coreIdentifier"), node);
|
||||
} else if (t.isCallExpression(node)) {
|
||||
} else if (this.isCallExpression()) {
|
||||
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
|
||||
|
||||
var callee = node.callee;
|
||||
@ -53,7 +54,7 @@ var astVisitor = {
|
||||
CORE_ID: file.get("coreIdentifier"),
|
||||
VALUE: callee.object
|
||||
});
|
||||
} else if (t.isBinaryExpression(node)) {
|
||||
} else if (this.isBinaryExpression()) {
|
||||
// Symbol.iterator in arr -> core.$for.isIterable(arr)
|
||||
|
||||
if (node.operator !== "in") return;
|
||||
@ -94,7 +95,7 @@ export function pre(file) {
|
||||
}
|
||||
|
||||
export function Identifier(node, parent, scope, file) {
|
||||
if (t.isReferencedIdentifier(node, parent, { name: "regeneratorRuntime" })) {
|
||||
if (this.isReferencedIdentifier({ name: "regeneratorRuntime" })) {
|
||||
return file.get("regeneratorIdentifier");
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,8 +6,7 @@ export var playground = true;
|
||||
|
||||
build(exports, {
|
||||
is(node, file) {
|
||||
var is = t.isAssignmentExpression(node) && node.operator === "||=";
|
||||
if (is) {
|
||||
if (t.isAssignmentExpression(node, { operator: "||=" })) {
|
||||
var left = node.left;
|
||||
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
|
||||
throw file.errorWithNode(left, messages.get("expectedMemberExpressionOrIdentifier"));
|
||||
|
||||
@ -5,7 +5,7 @@ export var playground = true;
|
||||
|
||||
build(exports, {
|
||||
is(node) {
|
||||
var is = t.isAssignmentExpression(node) && node.operator === "?=";
|
||||
var is = t.isAssignmentExpression(node, { operator: "?=" });
|
||||
if (is) t.assertMemberExpression(node.left);
|
||||
return is;
|
||||
},
|
||||
|
||||
@ -4,9 +4,9 @@ export var playground = true;
|
||||
|
||||
var visitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isFunction(node)) return this.skip();
|
||||
if (this.isFunction()) return this.skip();
|
||||
|
||||
if (t.isReturnStatement(node) && node.argument) {
|
||||
if (this.isReturnStatement() && node.argument) {
|
||||
node.argument = t.memberExpression(t.callExpression(state.file.addHelper("define-property"), [
|
||||
t.thisExpression(),
|
||||
state.key,
|
||||
|
||||
@ -3,7 +3,7 @@ import t from "../../../types";
|
||||
export var optional = true;
|
||||
|
||||
export function Identifier(node, parent) {
|
||||
if (node.name === "undefined" && t.isReferenced(node, parent)) {
|
||||
if (node.name === "undefined" && this.isReferenced()) {
|
||||
return t.unaryExpression("void", t.literal(0), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import t from "../../../types";
|
||||
export var optional = true;
|
||||
|
||||
export function ExpressionStatement(node) {
|
||||
if (t.isIdentifier(node.expression, { name: "debugger" })) {
|
||||
if (this.get("expression").isIdentifier({ name: "debugger" })) {
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import levenshtein from "leven";
|
||||
import * as messages from "../../../messages";
|
||||
import t from "../../../types";
|
||||
|
||||
export var optional = true;
|
||||
|
||||
export function Identifier(node, parent, scope, file) {
|
||||
if (!t.isReferenced(node, parent)) return;
|
||||
if (!this.isReferenced()) return;
|
||||
if (scope.hasBinding(node.name)) return;
|
||||
|
||||
// get the closest declaration to offer as a suggestion
|
||||
|
||||
@ -2,7 +2,7 @@ import TraversalPath from "./path";
|
||||
import flatten from "lodash/array/flatten";
|
||||
import compact from "lodash/array/compact";
|
||||
|
||||
export default class TraversalConext {
|
||||
export default class TraversalContext {
|
||||
constructor(scope, opts, state, parentPath) {
|
||||
this.shouldFlatten = false;
|
||||
this.parentPath = parentPath;
|
||||
@ -17,7 +17,7 @@ export default class TraversalConext {
|
||||
}
|
||||
|
||||
visitNode(node, obj, key) {
|
||||
var iteration = new TraversalPath(this, node, obj, key);
|
||||
var iteration = TraversalPath.get(this.parentPath, this, node, obj, key);
|
||||
return iteration.visit();
|
||||
}
|
||||
|
||||
|
||||
@ -42,13 +42,14 @@ traverse.node = function (node, opts, scope, state, parentPath) {
|
||||
function clearNode(node) {
|
||||
node._declarations = null;
|
||||
node.extendedRange = null;
|
||||
node._scopeInfo = null;
|
||||
node.tokens = null;
|
||||
node.range = null;
|
||||
node.start = null;
|
||||
node.end = null;
|
||||
node.loc = null;
|
||||
node.raw = null;
|
||||
node._scopeInfo = null;
|
||||
node._paths = null;
|
||||
node.tokens = null;
|
||||
node.range = null;
|
||||
node.start = null;
|
||||
node.end = null;
|
||||
node.loc = null;
|
||||
node.raw = null;
|
||||
|
||||
if (Array.isArray(node.trailingComments)) {
|
||||
clearComments(node.trailingComments);
|
||||
@ -57,11 +58,18 @@ function clearNode(node) {
|
||||
if (Array.isArray(node.leadingComments)) {
|
||||
clearComments(node.leadingComments);
|
||||
}
|
||||
|
||||
for (var key in node) {
|
||||
var val = node[key];
|
||||
if (Array.isArray(val)) {
|
||||
delete val._paths;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var clearVisitor = {
|
||||
noScope: true,
|
||||
enter: clearNode
|
||||
exit: clearNode
|
||||
};
|
||||
|
||||
function clearComments(comments) {
|
||||
@ -71,8 +79,8 @@ function clearComments(comments) {
|
||||
}
|
||||
|
||||
traverse.removeProperties = function (tree) {
|
||||
clearNode(tree);
|
||||
traverse(tree, clearVisitor);
|
||||
clearNode(tree);
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
@ -4,23 +4,34 @@ import Scope from "./scope";
|
||||
import t from "../types";
|
||||
|
||||
export default class TraversalPath {
|
||||
constructor(context, parent, container, key) {
|
||||
this.shouldRemove = false;
|
||||
this.shouldSkip = false;
|
||||
this.shouldStop = false;
|
||||
constructor(parentPath, parent, container) {
|
||||
this.parentPath = parentPath;
|
||||
this.container = container;
|
||||
this.parent = parent;
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
this.parentPath = context.parentPath;
|
||||
this.context = context;
|
||||
this.state = this.context.state;
|
||||
this.opts = this.context.opts;
|
||||
static get(parentPath, context, parent, container, key) {
|
||||
var targetNode = container[key];
|
||||
var paths = container._paths ||= [];
|
||||
var path;
|
||||
|
||||
this.container = container;
|
||||
this.key = key;
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
var pathCheck = paths[i];
|
||||
if (pathCheck.node === targetNode) {
|
||||
path = pathCheck;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.parent = parent;
|
||||
this.state = context.state;
|
||||
if (!path) {
|
||||
path = new TraversalPath(parentPath, parent, container);
|
||||
paths.push(path);
|
||||
}
|
||||
|
||||
this.setScope();
|
||||
path.setContext(context, key);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static getScope(node, parent, scope) {
|
||||
@ -34,10 +45,31 @@ export default class TraversalPath {
|
||||
return ourScope;
|
||||
}
|
||||
|
||||
setData(key, val) {
|
||||
return this.data[key] = val;
|
||||
}
|
||||
|
||||
getData(key) {
|
||||
return this.data[key];
|
||||
}
|
||||
|
||||
setScope() {
|
||||
this.scope = TraversalPath.getScope(this.node, this.parent, this.context.scope);
|
||||
}
|
||||
|
||||
setContext(context, key) {
|
||||
this.shouldRemove = false;
|
||||
this.shouldSkip = false;
|
||||
this.shouldStop = false;
|
||||
|
||||
this.context = context;
|
||||
this.state = context.state;
|
||||
this.opts = context.opts;
|
||||
this.key = key;
|
||||
|
||||
this.setScope();
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.shouldRemove = true;
|
||||
this.shouldSkip = true;
|
||||
@ -114,14 +146,13 @@ export default class TraversalPath {
|
||||
}
|
||||
}
|
||||
|
||||
visit() {
|
||||
var opts = this.opts;
|
||||
var node = this.node;
|
||||
isBlacklisted() {
|
||||
var blacklist = this.opts.blacklist;
|
||||
return blacklist && blacklist.indexOf(this.node.type) > -1;
|
||||
}
|
||||
|
||||
// type is blacklisted
|
||||
if (opts.blacklist && opts.blacklist.indexOf(node.type) > -1) {
|
||||
return false;
|
||||
}
|
||||
visit() {
|
||||
if (this.isBlacklisted()) return false;
|
||||
|
||||
this.call("enter");
|
||||
|
||||
@ -129,7 +160,8 @@ export default class TraversalPath {
|
||||
return this.shouldStop;
|
||||
}
|
||||
|
||||
node = this.node;
|
||||
var node = this.node;
|
||||
var opts = this.opts;
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
// traverse over these replacement nodes we purposely don't call exitNode
|
||||
@ -139,13 +171,38 @@ export default class TraversalPath {
|
||||
}
|
||||
} else {
|
||||
traverse.node(node, opts, this.scope, this.state, this);
|
||||
|
||||
this.call("exit");
|
||||
}
|
||||
|
||||
return this.shouldStop;
|
||||
}
|
||||
|
||||
isReferencedIdentifier() {
|
||||
return t.isReferencedIdentifier(this.node);
|
||||
get(key) {
|
||||
return TraversalPath.get(this, this.context, this.node, this.node, key);
|
||||
}
|
||||
|
||||
isReferencedIdentifier(opts) {
|
||||
return t.isReferencedIdentifier(this.node, this.parent, opts);
|
||||
}
|
||||
|
||||
isReferenced() {
|
||||
return t.isReferenced(this.node, this.parent);
|
||||
}
|
||||
|
||||
isScope() {
|
||||
return t.isScope(this.node, this.parent);
|
||||
}
|
||||
|
||||
getBindingIdentifiers() {
|
||||
return t.getBindingIdentifiers(this.node);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < t.TYPES.length; i++) {
|
||||
let type = t.TYPES[i];
|
||||
let typeKey = `is${type}`;
|
||||
TraversalPath.prototype[typeKey] = function (opts) {
|
||||
return t[typeKey](this.node, opts);
|
||||
};
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import isString from "lodash/lang/isString";
|
||||
import compact from "lodash/array/compact";
|
||||
import esutils from "esutils";
|
||||
import object from "../helpers/object";
|
||||
import clone from "lodash/lang/clone";
|
||||
import each from "lodash/collection/each";
|
||||
import uniq from "lodash/array/uniq";
|
||||
|
||||
@ -48,7 +49,7 @@ each(t.VISITOR_KEYS, function (keys, type) {
|
||||
|
||||
each(t.ALIAS_KEYS, function (aliases, type) {
|
||||
each(aliases, function (alias) {
|
||||
var types = t.FLIPPED_ALIAS_KEYS[alias] = t.FLIPPED_ALIAS_KEYS[alias] || [];
|
||||
var types = t.FLIPPED_ALIAS_KEYS[alias] ||= [];
|
||||
types.push(type);
|
||||
});
|
||||
});
|
||||
@ -58,6 +59,8 @@ each(t.FLIPPED_ALIAS_KEYS, function (types, type) {
|
||||
registerType(type, false);
|
||||
});
|
||||
|
||||
t.TYPES = Object.keys(t.VISITOR_KEYS).concat(Object.keys(t.FLIPPED_ALIAS_KEYS));
|
||||
|
||||
/**
|
||||
* Returns whether `node` is of given `type`.
|
||||
*
|
||||
@ -413,6 +416,49 @@ t.ensureBlock = function (node, key) {
|
||||
return node[key] = t.toBlock(node[key], node);
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
t.clone = function (node) {
|
||||
var newNode = {};
|
||||
for (var key in node) {
|
||||
if (key[0] === "_") continue;
|
||||
newNode[key] = node[key];
|
||||
}
|
||||
return newNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
t.cloneDeep = function (node) {
|
||||
var newNode = {};
|
||||
|
||||
for (var key in node) {
|
||||
var val = node[key];
|
||||
|
||||
if (val) {
|
||||
if (val.type) {
|
||||
val = t.cloneDeep(val);
|
||||
} else if (Array.isArray(val)) {
|
||||
val = val.map(t.cloneDeep);
|
||||
}
|
||||
}
|
||||
|
||||
newNode[key] = val;
|
||||
}
|
||||
|
||||
return newNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a function that when called will return whether or not the
|
||||
* input `node` `MemberExpression` matches the input `match`.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user