babel-traverse
Advanced tools
Comparing version 6.13.0 to 6.14.0
@@ -38,7 +38,2 @@ "use strict"; | ||
/** | ||
* This method does a simple check to determine whether or not we really need to attempt | ||
* visit a node. This will prevent us from constructing a NodePath. | ||
*/ | ||
TraversalContext.prototype.shouldVisit = function shouldVisit(node) { | ||
@@ -48,10 +43,7 @@ var opts = this.opts; | ||
// check if we have a visitor for this node | ||
if (opts[node.type]) return true; | ||
// check if we're going to traverse into this node | ||
var keys = t.VISITOR_KEYS[node.type]; | ||
if (!keys || !keys.length) return false; | ||
// we need to traverse into this node so ensure that it has children to traverse into! | ||
for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { | ||
@@ -102,3 +94,2 @@ var _ref; | ||
TraversalContext.prototype.visitMultiple = function visitMultiple(container, parent, listKey) { | ||
// nothing to traverse! | ||
if (container.length === 0) return false; | ||
@@ -108,3 +99,2 @@ | ||
// build up initial queue | ||
for (var key = 0; key < container.length; key++) { | ||
@@ -129,3 +119,2 @@ var node = container[key]; | ||
TraversalContext.prototype.visitQueue = function visitQueue(queue) { | ||
// set queue | ||
this.queue = queue; | ||
@@ -137,3 +126,2 @@ this.priorityQueue = []; | ||
// visit the queue | ||
for (var _iterator2 = queue, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { | ||
@@ -156,9 +144,5 @@ var _ref2; | ||
if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) { | ||
// The context might already have been pushed when this path was inserted and queued. | ||
// If we always re-pushed here, we could get duplicates and risk leaving contexts | ||
// on the stack after the traversal has completed, which could break things. | ||
path.pushContext(this); | ||
} | ||
// this path no longer belongs to the tree | ||
if (path.key === null) continue; | ||
@@ -170,3 +154,2 @@ | ||
// ensure we don't visit the same node twice | ||
if (visited.indexOf(path.node) >= 0) continue; | ||
@@ -188,3 +171,2 @@ visited.push(path.node); | ||
// clear queue | ||
for (var _iterator3 = queue, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { | ||
@@ -207,3 +189,2 @@ var _ref3; | ||
// clear queue | ||
this.queue = null; | ||
@@ -210,0 +191,0 @@ |
@@ -223,6 +223,4 @@ "use strict"; | ||
traverse.hasType = function (tree, scope, type, blacklistTypes) { | ||
// the node we're searching in is blacklisted | ||
if ((0, _includes2.default)(blacklistTypes, tree.type)) return false; | ||
// the type we're looking for is the same as the passed node | ||
if (tree.type === type) return true; | ||
@@ -229,0 +227,0 @@ |
@@ -31,9 +31,2 @@ "use strict"; | ||
/** | ||
* Call the provided `callback` with the `NodePath`s of all the parents. | ||
* When the `callback` returns a truthy value, we return that node path. | ||
*/ | ||
// This file contains that retrieve or validate anything related to the current paths ancestry. | ||
function findParent(callback) { | ||
@@ -47,6 +40,2 @@ var path = this; | ||
/** | ||
* Description | ||
*/ | ||
function find(callback) { | ||
@@ -60,6 +49,2 @@ var path = this; | ||
/** | ||
* Get the parent function of the current path. | ||
*/ | ||
function getFunctionParent() { | ||
@@ -71,6 +56,2 @@ return this.findParent(function (path) { | ||
/** | ||
* Walk up the tree until we hit a parent node path in a list. | ||
*/ | ||
function getStatementParent() { | ||
@@ -85,10 +66,2 @@ var path = this; | ||
/** | ||
* Get the deepest common ancestor and then from it, get the earliest relationship path | ||
* to that ancestor. | ||
* | ||
* Earliest is defined as being "before" all the other nodes in terms of list container | ||
* position and visiting key. | ||
*/ | ||
function getEarliestCommonAncestorFrom(paths) { | ||
@@ -115,3 +88,2 @@ return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) { | ||
// first path | ||
if (!earliest) { | ||
@@ -122,5 +94,3 @@ earliest = path; | ||
// handle containers | ||
if (path.listKey && earliest.listKey === path.listKey) { | ||
// we're in the same container so check if we're earlier | ||
if (path.key < earliest.key) { | ||
@@ -132,7 +102,5 @@ earliest = path; | ||
// handle keys | ||
var earliestKeyIndex = keys.indexOf(earliest.parentKey); | ||
var currentKeyIndex = keys.indexOf(path.parentKey); | ||
if (earliestKeyIndex > currentKeyIndex) { | ||
// key appears before so it's earlier | ||
earliest = path; | ||
@@ -146,8 +114,2 @@ } | ||
/** | ||
* Get the earliest path in the tree where the provided `paths` intersect. | ||
* | ||
* TODO: Possible optimisation target. | ||
*/ | ||
function getDeepestCommonAncestorFrom(paths, filter) { | ||
@@ -164,10 +126,7 @@ var _this = this; | ||
// minimum depth of the tree so we know the highest node | ||
var minDepth = Infinity; | ||
// last common ancestor | ||
var lastCommonIndex = void 0, | ||
lastCommon = void 0; | ||
// get the ancestors of the path, breaking when the parent exceeds ourselves | ||
var ancestries = paths.map(function (path) { | ||
@@ -180,3 +139,2 @@ var ancestry = []; | ||
// save min depth to avoid going too far in | ||
if (ancestry.length < minDepth) { | ||
@@ -189,6 +147,4 @@ minDepth = ancestry.length; | ||
// get the first ancestry so we have a seed to assess all other ancestries with | ||
var first = ancestries[0]; | ||
// check ancestor equality | ||
depthLoop: for (var i = 0; i < minDepth; i++) { | ||
@@ -212,3 +168,2 @@ var shouldMatch = first[i]; | ||
if (ancestry[i] !== shouldMatch) { | ||
// we've hit a snag | ||
break depthLoop; | ||
@@ -218,3 +173,2 @@ } | ||
// next iteration may break so store these so they can be returned | ||
lastCommonIndex = i; | ||
@@ -235,8 +189,2 @@ lastCommon = shouldMatch; | ||
/** | ||
* Build an array of node paths containing the entire ancestry of the current node path. | ||
* | ||
* NOTE: The current node path is included in this. | ||
*/ | ||
function getAncestry() { | ||
@@ -276,35 +224,2 @@ var path = this; | ||
/** | ||
* Checks whether the binding for 'key' is a local binding in its current function context. | ||
* | ||
* Checks if the current path either is, or has a direct parent function that is, inside | ||
* of a function that is marked for shadowing of a binding matching 'key'. Also returns | ||
* the parent path if the parent path is an arrow, since arrow functions pass through | ||
* binding values to their parent, meaning they have no local bindings. | ||
* | ||
* Shadowing means that when the given binding is transformed, it will read the binding | ||
* value from the container containing the shadow function, rather than from inside the | ||
* shadow function. | ||
* | ||
* Function shadowing is acheieved by adding a "shadow" property on "FunctionExpression" | ||
* and "FunctionDeclaration" node types. | ||
* | ||
* Node's "shadow" props have the following behavior: | ||
* | ||
* - Boolean true will cause the function to shadow both "this" and "arguments". | ||
* - {this: false} Shadows "arguments" but not "this". | ||
* - {arguments: false} Shadows "this" but not "arguments". | ||
* | ||
* Separately, individual identifiers can be flagged with two flags: | ||
* | ||
* - _forceShadow - If truthy, this specific identifier will be bound in the closest | ||
* Function that is not flagged "shadow", or the Program. | ||
* - _shadowedFunctionLiteral - When set to a NodePath, this specific identifier will be bound | ||
* to this NodePath/Node or the Program. If this path is not found relative to the | ||
* starting location path, the closest function will be used. | ||
* | ||
* Please Note, these flags are for private internal use only and should be avoided. | ||
* Only "shadow" is a public property that other transforms may manipulate. | ||
*/ | ||
function inShadow(key) { | ||
@@ -319,7 +234,2 @@ var parentFn = this.isFunction() ? this : this.findParent(function (p) { | ||
// this is because sometimes we may have a `shadow` value of: | ||
// | ||
// { this: false } | ||
// | ||
// we need to catch this case if `inShadow` has been passed a `key` | ||
if (shadow && (!key || shadow[key] !== false)) { | ||
@@ -332,4 +242,3 @@ return parentFn; | ||
// normal function, we've found our function context | ||
return null; | ||
} |
@@ -7,8 +7,2 @@ "use strict"; | ||
exports.addComments = addComments; | ||
// This file contains methods responsible for dealing with comments. | ||
/** | ||
* Share comments amongst siblings. | ||
*/ | ||
function shareCommentsWithSiblings() { | ||
@@ -39,6 +33,2 @@ var node = this.node; | ||
/** | ||
* Give node `comments` of the specified `type`. | ||
*/ | ||
function addComments(type, comments) { | ||
@@ -45,0 +35,0 @@ if (!comments) return; |
@@ -52,3 +52,3 @@ "use strict"; | ||
return false; | ||
} // This file contains methods responsible for maintaining a TraversalContext. | ||
} | ||
@@ -80,3 +80,2 @@ function _call(fns) { | ||
// node has been replaced, it will have been requeued | ||
if (this.node !== node) return true; | ||
@@ -174,8 +173,2 @@ | ||
/** | ||
* Here we resync the node paths `key` and `container`. If they've changed according | ||
* to what we have stored internally then we attempt to resync by crawling and looking | ||
* for the new values. | ||
*/ | ||
function resync() { | ||
@@ -187,3 +180,2 @@ if (this.removed) return; | ||
this._resyncKey(); | ||
//this._resyncRemoved(); | ||
} | ||
@@ -202,5 +194,2 @@ | ||
// grrr, path key is out of sync. this is likely due to a modification to the AST | ||
// not done through our path APIs | ||
if (Array.isArray(this.container)) { | ||
@@ -220,3 +209,2 @@ for (var i = 0; i < this.container.length; i++) { | ||
// ¯\_(ツ)_/¯ who knows where it's gone lol | ||
this.key = null; | ||
@@ -231,3 +219,2 @@ } | ||
// container is out of sync. this is likely the result of it being reassigned | ||
this.container = newContainer || null; | ||
@@ -273,5 +260,2 @@ } | ||
// TODO(loganfsmyth): This should be switched back to queue in parent contexts | ||
// automatically once T2892 and T7160 have been resolved. See T7166. | ||
// let contexts = this._getQueueContexts(); | ||
var contexts = this.contexts; | ||
@@ -278,0 +262,0 @@ |
@@ -31,3 +31,3 @@ "use strict"; | ||
return key; | ||
} // This file contains methods that convert the path node into another node or some other type of data. | ||
} | ||
@@ -39,3 +39,2 @@ function ensureBlock() { | ||
function arrowFunctionToShadowed() { | ||
// todo: maybe error | ||
if (!this.isArrowFunctionExpression()) return; | ||
@@ -42,0 +41,0 @@ |
@@ -22,29 +22,5 @@ "use strict"; | ||
// This file contains Babels metainterpreter that can evaluate static code. | ||
/* eslint eqeqeq: 0 */ | ||
var VALID_CALLEES = ["String", "Number", "Math"]; /* eslint indent: 0 */ | ||
/* eslint max-len: 0 */ | ||
var VALID_CALLEES = ["String", "Number", "Math"]; | ||
var INVALID_METHODS = ["random"]; | ||
/** | ||
* Walk the input `node` and statically evaluate if it's truthy. | ||
* | ||
* Returning `true` when we're sure that the expression will evaluate to a | ||
* truthy value, `false` if we're sure that it will evaluate to a falsy | ||
* value and `undefined` if we aren't sure. Because of this please do not | ||
* rely on coercion when using this method and check with === if it's false. | ||
* | ||
* For example do: | ||
* | ||
* if (t.evaluateTruthy(node) === false) falsyLogic(); | ||
* | ||
* **AND NOT** | ||
* | ||
* if (!t.evaluateTruthy(node)) falsyLogic(); | ||
* | ||
*/ | ||
function evaluateTruthy() { | ||
@@ -55,17 +31,2 @@ var res = this.evaluate(); | ||
/** | ||
* Walk the input `node` and statically evaluate it. | ||
* | ||
* Returns an object in the form `{ confident, value }`. `confident` indicates | ||
* whether or not we had to drop out of evaluating the expression because of | ||
* hitting an unknown node that we couldn't confidently find the value of. | ||
* | ||
* Example: | ||
* | ||
* t.evaluate(parse("5 + 5")) // { confident: true, value: 10 } | ||
* t.evaluate(parse("!true")) // { confident: true, value: false } | ||
* t.evaluate(parse("foo + foo")) // { confident: false, value: undefined } | ||
* | ||
*/ | ||
function evaluate() { | ||
@@ -90,9 +51,2 @@ var confident = true; | ||
// we wrap the _evaluate method so we can track `seen` nodes, we push an item | ||
// to the map before we actually evaluate it so we can deopt on self recursive | ||
// nodes such as: | ||
// | ||
// var g = a ? 1 : 2, | ||
// a = g * this.foo | ||
// | ||
function evaluate(path) { | ||
@@ -162,9 +116,6 @@ var node = path.node; | ||
// not confident, evaluated an expression we don't like | ||
if (!confident) break; | ||
// add on cooked element | ||
str += elem.value.cooked; | ||
// add on interpolated expression if it's present | ||
var expr = _exprs[i++]; | ||
@@ -189,7 +140,5 @@ if (expr) str += String(evaluate(expr)); | ||
if (path.isExpressionWrapper()) { | ||
// TypeCastExpression, ExpressionStatement etc | ||
return evaluate(path.get("expression")); | ||
} | ||
// "foo".length | ||
if (path.isMemberExpression() && !path.parentPath.isCallExpression({ callee: node })) { | ||
@@ -210,2 +159,7 @@ var property = path.get("property"); | ||
var binding = path.scope.getBinding(node.name); | ||
if (binding && binding.constantViolations.length > 0) { | ||
return deopt(binding.path); | ||
} | ||
if (binding && binding.hasValue) { | ||
@@ -233,3 +187,2 @@ return binding.value; | ||
if (node.operator === "void") { | ||
// we don't need to evaluate the argument to know what this will return | ||
return undefined; | ||
@@ -287,9 +240,5 @@ } | ||
if (path.isObjectExpression()) { | ||
// todo | ||
} | ||
if (path.isObjectExpression()) {} | ||
if (path.isLogicalExpression()) { | ||
// If we are confident that one side of an && is false, or the left | ||
// side of an || is true, we can be confident about the entire expression | ||
var wasConfident = confident; | ||
@@ -305,4 +254,2 @@ var left = evaluate(path.get("left")); | ||
case "||": | ||
// TODO consider having a "truthy type" that doesn't bail on | ||
// left uncertainity but can still evaluate to truthy. | ||
if (left && leftConfident) { | ||
@@ -382,3 +329,2 @@ confident = true; | ||
// Number(1); | ||
if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name, true) && VALID_CALLEES.indexOf(callee.node.name) >= 0) { | ||
@@ -392,3 +338,2 @@ func = global[node.callee.name]; | ||
// Math.min(1, 2) | ||
if (_object.isIdentifier() && _property.isIdentifier() && VALID_CALLEES.indexOf(_object.node.name) >= 0 && INVALID_METHODS.indexOf(_property.node.name) < 0) { | ||
@@ -399,3 +344,2 @@ context = global[_object.node.name]; | ||
// "abc".charCodeAt(4) | ||
if (_object.isLiteral() && _property.isIdentifier()) { | ||
@@ -402,0 +346,0 @@ var _type = (0, _typeof3.default)(_object.node.value); |
@@ -47,3 +47,3 @@ "use strict"; | ||
return path; | ||
} // This file contains methods responsible for dealing with/retrieving children or siblings. | ||
} | ||
@@ -99,6 +99,4 @@ function getOpposite() { | ||
if (parts.length === 1) { | ||
// "foo" | ||
return this._getKey(key, context); | ||
} else { | ||
// "foo.bar" | ||
return this._getPattern(parts, context); | ||
@@ -115,3 +113,2 @@ } | ||
if (Array.isArray(container)) { | ||
// requested a container so give them all the paths | ||
return container.map(function (_, i) { | ||
@@ -118,0 +115,0 @@ return _index2.default.get({ |
@@ -47,4 +47,2 @@ "use strict"; | ||
/* eslint max-len: 0 */ | ||
var _debug = (0, _debug3.default)("babel"); | ||
@@ -123,3 +121,2 @@ | ||
// we're entering a new scope so let's construct it! | ||
if (this.isScope()) { | ||
@@ -126,0 +123,0 @@ ourScope = new _scope2.default(this, scope); |
@@ -28,6 +28,2 @@ "use strict"; | ||
/** | ||
* Infer the type of the current `NodePath`. | ||
*/ | ||
function getTypeAnnotation() { | ||
@@ -41,6 +37,2 @@ if (this.typeAnnotation) return this.typeAnnotation; | ||
/** | ||
* todo: split up this method | ||
*/ | ||
function _getTypeAnnotation() { | ||
@@ -50,3 +42,2 @@ var node = this.node; | ||
if (!node) { | ||
// handle initializerless variables, add in checks for loop initializers too | ||
if (this.key === "init" && this.parentPath.isVariableDeclarator()) { | ||
@@ -56,3 +47,2 @@ var declar = this.parentPath.parentPath; | ||
// for (let NODE in bar) {} | ||
if (declar.key === "left" && declarParent.isForInStatement()) { | ||
@@ -62,3 +52,2 @@ return t.stringTypeAnnotation(); | ||
// for (let NODE of bar) {} | ||
if (declar.key === "left" && declarParent.isForOfStatement()) { | ||
@@ -65,0 +54,0 @@ return t.anyTypeAnnotation(); |
@@ -12,4 +12,2 @@ "use strict"; | ||
// check if a binding exists of this value and if so then return a union type of all | ||
// possible types that the binding could be | ||
var binding = this.scope.getBinding(node.name); | ||
@@ -24,3 +22,2 @@ if (binding) { | ||
// built-in values | ||
if (node.name === "undefined") { | ||
@@ -30,5 +27,3 @@ return t.voidTypeAnnotation(); | ||
return t.numberTypeAnnotation(); | ||
} else if (node.name === "arguments") { | ||
// todo | ||
} | ||
} else if (node.name === "arguments") {} | ||
}; | ||
@@ -58,3 +53,2 @@ | ||
// remove constant violations observed before the IfStatement | ||
constantViolations = constantViolations.filter(function (path) { | ||
@@ -64,3 +58,2 @@ return testConstantViolations.indexOf(path) < 0; | ||
// clear current types and add in observed test type | ||
types.push(testType.typeAnnotation); | ||
@@ -71,30 +64,4 @@ })(); | ||
if (constantViolations.length) { | ||
// pick one constant from each scope which will represent the last possible | ||
// control flow path that it could've taken/been | ||
/* This code is broken for the following problems: | ||
* It thinks that assignments can only happen in scopes. | ||
* What about conditionals, if statements without block, | ||
* or guarded assignments. | ||
* It also checks to see if one of the assignments is in the | ||
* same scope and uses that as the only "violation". However, | ||
* the binding is returned by `getConstantViolationsBefore` so we for | ||
* sure always going to return that as the only "violation". | ||
let rawConstantViolations = constantViolations.reverse(); | ||
let visitedScopes = []; | ||
constantViolations = []; | ||
for (let violation of (rawConstantViolations: Array<NodePath>)) { | ||
let violationScope = violation.scope; | ||
if (visitedScopes.indexOf(violationScope) >= 0) continue; | ||
visitedScopes.push(violationScope); | ||
constantViolations.push(violation); | ||
if (violationScope === path.scope) { | ||
constantViolations = [violation]; | ||
break; | ||
} | ||
}*/ | ||
// add back on function constant violations since we can't track calls | ||
constantViolations = constantViolations.concat(functionConstantViolations); | ||
// push on inferred types of violated paths | ||
for (var _iterator = constantViolations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { | ||
@@ -158,3 +125,2 @@ var _ref; | ||
// | ||
var typeofPath = void 0; | ||
@@ -171,14 +137,10 @@ var typePath = void 0; | ||
// ensure that the type path is a Literal | ||
typePath = typePath.resolve(); | ||
if (!typePath.isLiteral()) return; | ||
// and that it's a string so we can infer it | ||
var typeValue = typePath.node.value; | ||
if (typeof typeValue !== "string") return; | ||
// and that the argument of the typeof path references us! | ||
if (!typeofPath.get("argument").isIdentifier({ name: name })) return; | ||
// turn type value into a type annotation | ||
return t.createTypeAnnotationBasedOnTypeof(typePath.node.value); | ||
@@ -185,0 +147,0 @@ } |
@@ -62,3 +62,2 @@ "use strict"; | ||
if (this.get("callee").isIdentifier()) { | ||
// only resolve identifier callee | ||
return t.genericTypeAnnotation(node.callee); | ||
@@ -98,10 +97,7 @@ } | ||
if (left.isBaseType("number") && right.isBaseType("number")) { | ||
// both numbers so this will be a number | ||
return t.numberTypeAnnotation(); | ||
} else if (left.isBaseType("string") || right.isBaseType("string")) { | ||
// one is a string so the result will be a string | ||
return t.stringTypeAnnotation(); | ||
} | ||
// unsure if left and right are strings or numbers so stay on the safe side | ||
return t.unionTypeAnnotation([t.stringTypeAnnotation(), t.numberTypeAnnotation()]); | ||
@@ -195,7 +191,5 @@ } | ||
return callee.node.returnType; | ||
} else { | ||
// todo: get union type of all return arguments | ||
} | ||
} else {} | ||
} | ||
} | ||
} |
@@ -44,11 +44,3 @@ "use strict"; | ||
/** | ||
* Match the current node if it matches the provided `pattern`. | ||
* | ||
* For example, given the match `React.createClass` it would match the | ||
* parsed nodes of `React.createClass` and `React["createClass"]`. | ||
*/ | ||
function matchesPattern(pattern, allowPartial) { | ||
// not a member expression | ||
if (!this.isMemberExpression()) return false; | ||
@@ -73,10 +65,7 @@ | ||
if (t.isIdentifier(node)) { | ||
// this part doesn't match | ||
if (!matches(node.name)) return false; | ||
} else if (t.isLiteral(node)) { | ||
// this part doesn't match | ||
if (!matches(node.value)) return false; | ||
} else if (t.isMemberExpression(node)) { | ||
if (node.computed && !t.isLiteral(node.property)) { | ||
// we can't deal with this | ||
return false; | ||
@@ -91,7 +80,5 @@ } else { | ||
} else { | ||
// we can't deal with this | ||
return false; | ||
} | ||
// too many parts | ||
if (++i > parts.length) { | ||
@@ -105,9 +92,2 @@ return false; | ||
/** | ||
* Check whether we have the input `key`. If the `key` references an array then we check | ||
* if the array has any items, otherwise we just check if it's falsy. | ||
*/ | ||
// This file contains methods responsible for introspecting the current path for certain values. | ||
function has(key) { | ||
@@ -122,6 +102,2 @@ var val = this.node && this.node[key]; | ||
/** | ||
* Description | ||
*/ | ||
function isStatic() { | ||
@@ -131,12 +107,4 @@ return this.scope.isStatic(this.node); | ||
/** | ||
* Alias of `has`. | ||
*/ | ||
var is = exports.is = has; | ||
/** | ||
* Opposite of `has`. | ||
*/ | ||
function isnt(key) { | ||
@@ -146,6 +114,2 @@ return !this.has(key); | ||
/** | ||
* Check whether the path node `key` strict equals `value`. | ||
*/ | ||
function equals(key, value) { | ||
@@ -155,7 +119,2 @@ return this.node[key] === value; | ||
/** | ||
* Check the type against our stored internal type of the node. This is handy when a node has | ||
* been removed yet we still internally know the type and need it to calculate node replacement. | ||
*/ | ||
function isNodeType(type) { | ||
@@ -165,12 +124,2 @@ return t.isType(this.type, type); | ||
/** | ||
* This checks whether or not we're in one of the following positions: | ||
* | ||
* for (KEY in right); | ||
* for (KEY;;); | ||
* | ||
* This is because these spots allow VariableDeclarations AND normal expressions so we need | ||
* to tell the path replacement that it's ok to replace this with an expression. | ||
*/ | ||
function canHaveVariableDeclarationOrExpression() { | ||
@@ -180,10 +129,2 @@ return (this.key === "init" || this.key === "left") && this.parentPath.isFor(); | ||
/** | ||
* This checks whether we are swapping an arrow function's body between an | ||
* expression and a block statement (or vice versa). | ||
* | ||
* This is because arrow functions may implicitly return an expression, which | ||
* is the same as containing a block statement. | ||
*/ | ||
function canSwapBetweenExpressionAndStatement(replacement) { | ||
@@ -203,6 +144,2 @@ if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) { | ||
/** | ||
* Check whether the current path references a completion record | ||
*/ | ||
function isCompletionRecord(allowInsideFunction) { | ||
@@ -215,3 +152,2 @@ var path = this; | ||
// we're in a function so can't be a completion record | ||
if (path.isFunction() && !first) { | ||
@@ -223,4 +159,2 @@ return !!allowInsideFunction; | ||
// check to see if we're the last item in the container and if we are | ||
// we're a completion record! | ||
if (Array.isArray(container) && path.key !== container.length - 1) { | ||
@@ -234,7 +168,2 @@ return false; | ||
/** | ||
* Check whether or not the current `key` allows either a single statement or block statement | ||
* so we can explode it if necessary. | ||
*/ | ||
function isStatementOrBlock() { | ||
@@ -248,6 +177,2 @@ if (this.parentPath.isLabeledStatement() || t.isBlockStatement(this.container)) { | ||
/** | ||
* Check if the currently assigned path references the `importName` of `moduleSource`. | ||
*/ | ||
function referencesImport(moduleSource, importName) { | ||
@@ -263,3 +188,2 @@ if (!this.isReferencedIdentifier()) return false; | ||
// check moduleSource | ||
if (parent.node.source.value === moduleSource) { | ||
@@ -286,6 +210,2 @@ if (!importName) return true; | ||
/** | ||
* Get the source code associated with this node. | ||
*/ | ||
function getSource() { | ||
@@ -304,16 +224,6 @@ var node = this.node; | ||
/** | ||
* Given a `target` check the execution status of it relative to the current path. | ||
* | ||
* "Execution status" simply refers to where or not we **think** this will execuete | ||
* before or after the input `target` element. | ||
*/ | ||
function _guessExecutionStatusRelativeTo(target) { | ||
// check if the two paths are in different functions, we can't track execution of these | ||
var targetFuncParent = target.scope.getFunctionParent(); | ||
var selfFuncParent = this.scope.getFunctionParent(); | ||
// here we check the `node` equality as sometimes we may have different paths for the | ||
// same node due to path thrashing | ||
if (targetFuncParent.node !== selfFuncParent.node) { | ||
@@ -333,3 +243,2 @@ var status = this._guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent); | ||
// get ancestor where the branches intersect | ||
var commonPath = void 0; | ||
@@ -350,3 +259,2 @@ var targetIndex = void 0; | ||
// get the relationship paths that associate these nodes to their common ancestor | ||
var targetRelationship = targetPaths[targetIndex - 1]; | ||
@@ -358,3 +266,2 @@ var selfRelationship = selfPaths[selfIndex - 1]; | ||
// container list so let's see which one is after the other | ||
if (targetRelationship.listKey && targetRelationship.container === selfRelationship.container) { | ||
@@ -364,3 +271,2 @@ return targetRelationship.key > selfRelationship.key ? "before" : "after"; | ||
// otherwise we're associated by a parent node, check which key comes before the other | ||
var targetKeyPosition = t.VISITOR_KEYS[targetRelationship.type].indexOf(targetRelationship.key); | ||
@@ -375,9 +281,4 @@ var selfKeyPosition = t.VISITOR_KEYS[selfRelationship.type].indexOf(selfRelationship.key); | ||
// so we're in a completely different function, if this is a function declaration | ||
// then we can be a bit smarter and handle cases where the function is either | ||
// a. not called at all (part of an export) | ||
// b. called directly | ||
var binding = targetFuncPath.scope.getBinding(targetFuncPath.node.id.name); | ||
// no references! | ||
if (!binding.references) return "before"; | ||
@@ -387,3 +288,2 @@ | ||
// verify that all of the references are calls | ||
for (var _iterator = referencePaths, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { | ||
@@ -410,3 +310,2 @@ var _ref; | ||
// verify that all the calls have the same execution status | ||
for (var _iterator2 = referencePaths, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { | ||
@@ -426,4 +325,2 @@ var _ref2; | ||
// if a reference is a child of the function we're checking against then we can | ||
// safelty ignore it | ||
var childOfFunction = !!_path.find(function (path) { | ||
@@ -446,6 +343,2 @@ return path.node === targetFuncPath.node; | ||
/** | ||
* Resolve a "pointer" `NodePath` to it's absolute path. | ||
*/ | ||
function resolve(dangerous, resolved) { | ||
@@ -458,7 +351,4 @@ return this._resolve(dangerous, resolved) || this; | ||
// detect infinite recursion | ||
// todo: possibly have a max length on this just to be safe | ||
if (resolved && resolved.indexOf(this) >= 0) return; | ||
// we store all the paths we've "resolved" in this array to prevent infinite recursion | ||
resolved = resolved || []; | ||
@@ -470,5 +360,3 @@ resolved.push(this); | ||
return this.get("init").resolve(dangerous, resolved); | ||
} else { | ||
// otherwise it's a request for a pattern and that's a bit more tricky | ||
} | ||
} else {} | ||
} else if (this.isReferencedIdentifier()) { | ||
@@ -478,6 +366,4 @@ var binding = this.scope.getBinding(this.node.name); | ||
// reassigned so we can't really resolve it | ||
if (!binding.constant) return; | ||
// todo - lookup module in dependency graph | ||
if (binding.kind === "module") return; | ||
@@ -488,3 +374,3 @@ | ||
var ret = binding.path.resolve(dangerous, resolved); | ||
// If the identifier resolves to parent node then we can't really resolve it. | ||
if (_this.find(function (parent) { | ||
@@ -505,4 +391,2 @@ return parent.node === ret.node; | ||
} else if (dangerous && this.isMemberExpression()) { | ||
// this is dangerous, as non-direct target assignments will mutate it's state | ||
// making this resolution inaccurate | ||
@@ -536,6 +420,4 @@ var targetKey = this.toComputedKey(); | ||
// { foo: obj } | ||
var match = prop.isnt("computed") && key.isIdentifier({ name: targetName }); | ||
// { "foo": "obj" } or { ["foo"]: "obj" } | ||
match = match || key.isLiteral({ value: targetName }); | ||
@@ -542,0 +424,0 @@ |
@@ -27,8 +27,5 @@ "use strict"; | ||
// direct references that we need to track to hoist this to the highest scope we can | ||
var binding = path.scope.getBinding(path.node.name); | ||
if (!binding) return; | ||
// this binding isn't accessible from the parent scope so we can safely ignore it | ||
// eg. it's in a closure etc | ||
if (binding !== state.scope.getBinding(path.node.name)) return; | ||
@@ -102,3 +99,2 @@ | ||
// don't allow paths that have their own lexical environments to pollute | ||
if (targetScope.path === path) { | ||
@@ -108,6 +104,4 @@ targetScope = path.scope.parent; | ||
// avoid hoisting to a scope that contains bindings that are executed after our attachment path | ||
if (targetScope.path.isProgram() || targetScope.path.isFunction()) { | ||
for (var name in this.bindings) { | ||
// check binding is a direct child of this paths scope | ||
if (!targetScope.hasOwnBinding(name)) continue; | ||
@@ -117,6 +111,4 @@ | ||
// allow parameter references | ||
if (binding.kind === "param") continue; | ||
// if this binding appears after our attachment point then don't hoist it | ||
if (binding.path.getStatementParent().key > path.key) return; | ||
@@ -137,9 +129,6 @@ } | ||
if (this.hasOwnParamBindings(scope)) { | ||
// should ignore this scope since it's ourselves | ||
if (this.scope === scope) return; | ||
// needs to be attached to the body | ||
return scope.path.get("body").get("body")[0]; | ||
} else { | ||
// doesn't need to be be attached to this scope | ||
return this.getNextScopeStatementParent(); | ||
@@ -179,6 +168,4 @@ } | ||
// don't bother hoisting to the same function as this will cause multiple branches to be evaluated more than once leading to a bad optimisation | ||
if (attachTo.getFunctionParent() === this.path.getFunctionParent()) return; | ||
// generate declaration and insert it to our point | ||
var uid = attachTo.scope.generateUidIdentifier("ref"); | ||
@@ -189,4 +176,2 @@ attachTo.insertBefore([t.variableDeclaration("var", [t.variableDeclarator(uid, this.path.node)])]); | ||
if (parent.isJSXElement() && this.path.container === parent.node.children) { | ||
// turning the `span` in `<div><span /></div>` to an expression so we need to wrap it with | ||
// an expression container | ||
uid = t.JSXExpressionContainer(uid); | ||
@@ -193,0 +178,0 @@ } |
"use strict"; | ||
exports.__esModule = true; | ||
// this file contains hooks that handle ancestry cleanup of parent nodes when removing children | ||
/** | ||
* Pre hooks should be used for either rejecting removal or delegating removal | ||
*/ | ||
var hooks = exports.hooks = [function (self, parent) { | ||
@@ -18,21 +12,10 @@ if (self.key === "body" && parent.isArrowFunctionExpression()) { | ||
// while (NODE); | ||
// removing the test of a while/switch, we can either just remove it entirely *or* turn the `test` into `true` | ||
// unlikely that the latter will ever be what's wanted so we just remove the loop to avoid infinite recursion | ||
removeParent = removeParent || self.key === "test" && (parent.isWhile() || parent.isSwitchCase()); | ||
// export NODE; | ||
// just remove a declaration for an export as this is no longer valid | ||
removeParent = removeParent || self.key === "declaration" && parent.isExportDeclaration(); | ||
// label: NODE | ||
// stray labeled statement with no body | ||
removeParent = removeParent || self.key === "body" && parent.isLabeledStatement(); | ||
// let NODE; | ||
// remove an entire declaration if there are no declarators left | ||
removeParent = removeParent || self.listKey === "declarations" && parent.isVariableDeclaration() && parent.node.declarations.length === 1; | ||
// NODE; | ||
// remove the entire expression statement if there's no expression | ||
removeParent = removeParent || self.key === "expression" && parent.isExpressionStatement(); | ||
@@ -46,5 +29,2 @@ | ||
if (parent.isSequenceExpression() && parent.node.expressions.length === 1) { | ||
// (node, NODE); | ||
// we've just removed the second element of a sequence expression so let's turn that sequence | ||
// expression into a regular expression | ||
parent.replaceWith(parent.node.expressions[0]); | ||
@@ -55,9 +35,5 @@ return true; | ||
if (parent.isBinary()) { | ||
// left + NODE; | ||
// NODE + right; | ||
// we're in a binary expression, better remove it and replace it with the last expression | ||
if (self.key === "left") { | ||
parent.replaceWith(parent.node.right); | ||
} else { | ||
// key === "right" | ||
parent.replaceWith(parent.node.left); | ||
@@ -64,0 +40,0 @@ } |
@@ -22,3 +22,2 @@ "use strict"; | ||
} else { | ||
// not a JSXIdentifier or an Identifier | ||
return false; | ||
@@ -28,3 +27,2 @@ } | ||
// check if node is referenced | ||
return t.isReferenced(node, parent); | ||
@@ -31,0 +29,0 @@ } |
@@ -43,9 +43,2 @@ "use strict"; | ||
/** | ||
* Insert the provided nodes before the current one. | ||
*/ | ||
/* eslint max-len: 0 */ | ||
// This file contains methods that modify the path/node in some ways. | ||
function insertBefore(nodes) { | ||
@@ -89,5 +82,2 @@ this._assertUnremoved(); | ||
// While this path may have a context, there is currently no guarantee that the context | ||
// will be the active context, because `popContext` may leave a final context in place. | ||
// We should remove this `if` and always push once T7171 has been resolved. | ||
if (this.context.queue) path.pushContext(this.context); | ||
@@ -165,7 +155,2 @@ paths.push(path); | ||
/** | ||
* Insert the provided nodes after the current one. When inserting nodes after an | ||
* expression, ensure that the completion record is correct by pushing the current node. | ||
*/ | ||
function insertAfter(nodes) { | ||
@@ -200,6 +185,2 @@ this._assertUnremoved(); | ||
/** | ||
* Update all sibling node paths after `fromIndex` by `incrementBy`. | ||
*/ | ||
function updateSiblingKeys(fromIndex, incrementBy) { | ||
@@ -254,4 +235,2 @@ if (!this.parent) return; | ||
// get the first path and insert our nodes before it, if it doesn't exist then it | ||
// doesn't matter, our nodes will be inserted anyway | ||
var path = _index2.default.get({ | ||
@@ -273,5 +252,2 @@ parentPath: this, | ||
// get an invisible path that represents the last node + 1 and replace it with our | ||
// nodes, effectively inlining it | ||
var container = this.node[listKey]; | ||
@@ -289,7 +265,2 @@ var path = _index2.default.get({ | ||
/** | ||
* Hoist the current node to the highest scope possible and return a UID | ||
* referencing it. | ||
*/ | ||
function hoist() { | ||
@@ -296,0 +267,0 @@ var scope = arguments.length <= 0 || arguments[0] === undefined ? this.scope : arguments[0]; |
@@ -32,3 +32,3 @@ "use strict"; | ||
this._markRemoved(); | ||
} // This file contains methods responsible for removing a node. | ||
} | ||
@@ -35,0 +35,0 @@ function _callRemovalHooks() { |
@@ -75,13 +75,2 @@ "use strict"; | ||
/** | ||
* Replace a node with an array of multiple. This method performs the following steps: | ||
* | ||
* - Inherit the comments of first provided node with that of the current node. | ||
* - Insert the provided nodes after the current node. | ||
* - Remove the current node. | ||
*/ | ||
/* eslint max-len: 0 */ | ||
// This file contains methods responsible for replacing a node with another. | ||
function replaceWithMultiple(nodes) { | ||
@@ -103,10 +92,2 @@ this.resync(); | ||
/** | ||
* Parse a string as an expression and replace the current node with the result. | ||
* | ||
* NOTE: This is typically not a good idea to use. Building source strings when | ||
* transforming ASTs is an antipattern and SHOULD NOT be encouraged. Even if it's | ||
* easier to use, your transforms will be extremely brittle. | ||
*/ | ||
function replaceWithSourceString(replacement) { | ||
@@ -132,6 +113,2 @@ this.resync(); | ||
/** | ||
* Replace the current node with another. | ||
*/ | ||
function replaceWith(replacement) { | ||
@@ -170,3 +147,2 @@ this.resync(); | ||
if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { | ||
// replacing a statement with an expression so wrap it in an expression statement | ||
replacement = t.expressionStatement(replacement); | ||
@@ -178,3 +154,2 @@ } | ||
if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { | ||
// replacing an expression with a statement so let's explode it | ||
return this.replaceExpressionWithStatements([replacement]); | ||
@@ -190,17 +165,10 @@ } | ||
// replace the node | ||
this._replaceWith(replacement); | ||
this.type = replacement.type; | ||
// potentially create new scope | ||
this.setScope(); | ||
// requeue for visiting | ||
this.requeue(); | ||
} | ||
/** | ||
* Description | ||
*/ | ||
function _replaceWith(node) { | ||
@@ -224,8 +192,2 @@ if (!this.container) { | ||
/** | ||
* This method takes an array of statements nodes and then explodes it | ||
* into expressions. This method retains completion records which is | ||
* extremely important to retain original semantics. | ||
*/ | ||
function replaceExpressionWithStatements(nodes) { | ||
@@ -243,3 +205,2 @@ this.resync(); | ||
// could be just one element due to the previous maybe popping | ||
if (exprs.length === 1) { | ||
@@ -259,3 +220,2 @@ this.replaceWith(exprs[0]); | ||
// add implicit returns to all ending expression statements | ||
var completionRecords = this.get("callee").getCompletionRecords(); | ||
@@ -262,0 +222,0 @@ for (var _iterator2 = completionRecords, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { |
@@ -11,13 +11,2 @@ "use strict"; | ||
/** | ||
* This class is responsible for a binding inside of a scope. | ||
* | ||
* It tracks the following: | ||
* | ||
* * Node path. | ||
* * Amount of times referenced by other nodes. | ||
* * Paths to nodes that reassign or modify this binding. | ||
* * The kind of binding. (Is it a parameter, declaration etc) | ||
*/ | ||
var Binding = function () { | ||
@@ -68,6 +57,2 @@ function Binding(_ref) { | ||
/** | ||
* Register a constant violation with the provided `path`. | ||
*/ | ||
Binding.prototype.reassign = function reassign(path) { | ||
@@ -81,6 +66,2 @@ this.constant = false; | ||
/** | ||
* Increment the amount of references to this binding. | ||
*/ | ||
Binding.prototype.reference = function reference(path) { | ||
@@ -95,6 +76,2 @@ if (this.referencePaths.indexOf(path) !== -1) { | ||
/** | ||
* Decrement the amount of references to this binding. | ||
*/ | ||
Binding.prototype.dereference = function dereference() { | ||
@@ -101,0 +78,0 @@ this.references--; |
@@ -63,15 +63,4 @@ "use strict"; | ||
// Number of calls to the crawl method to figure out whether we're | ||
// somewhere inside a call that was trigerred by call. This is meant | ||
// to be used to figure out whether a warning should be trigerred. | ||
// See `warnOnFlowBinding`. | ||
/* eslint max-len: 0 */ | ||
var _crawlCallsCount = 0; | ||
/** | ||
* To avoid creating a new Scope instance for each traversal, we maintain a cache on the | ||
* node itself containing all scopes it has been associated with. | ||
*/ | ||
function getCache(path, parentScope, self) { | ||
@@ -104,4 +93,2 @@ var scopes = _cache.scope.get(path.node) || []; | ||
// | ||
var collectorVisitor = { | ||
@@ -128,12 +115,6 @@ For: function For(path) { | ||
Declaration: function Declaration(path) { | ||
// delegate block scope handling to the `blockVariableVisitor` | ||
if (path.isBlockScoped()) return; | ||
// this will be hit again once we traverse into it after this iteration | ||
if (path.isExportDeclaration() && path.get("declaration").isDeclaration()) return; | ||
// TODO(amasad): remove support for flow as bindings (See warning below). | ||
//if (path.isFlow()) return; | ||
// we've ran into a declaration! | ||
path.scope.getFunctionParent().registerDeclaration(path); | ||
@@ -242,8 +223,2 @@ }, | ||
var Scope = function () { | ||
/** | ||
* This searches the current "scope" and collects all references/bindings | ||
* within. | ||
*/ | ||
function Scope(path, parentScope) { | ||
@@ -268,14 +243,2 @@ (0, _classCallCheck3.default)(this, Scope); | ||
/** | ||
* Globals. | ||
*/ | ||
/** | ||
* Variables available in current context. | ||
*/ | ||
/** | ||
* Traverse node with current scope and path. | ||
*/ | ||
Scope.prototype.traverse = function traverse(node, opts, state) { | ||
@@ -285,6 +248,2 @@ (0, _index2.default)(node, opts, this, state, this.path); | ||
/** | ||
* Generate a unique identifier and add it to the current scope. | ||
*/ | ||
Scope.prototype.generateDeclaredUidIdentifier = function generateDeclaredUidIdentifier() { | ||
@@ -298,6 +257,2 @@ var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; | ||
/** | ||
* Generate a unique identifier. | ||
*/ | ||
Scope.prototype.generateUidIdentifier = function generateUidIdentifier() { | ||
@@ -309,6 +264,2 @@ var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; | ||
/** | ||
* Generate a unique `_id1` binding. | ||
*/ | ||
Scope.prototype.generateUid = function generateUid() { | ||
@@ -333,6 +284,2 @@ var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; | ||
/** | ||
* Generate an `_id1`. | ||
*/ | ||
Scope.prototype._generateUid = function _generateUid(name, i) { | ||
@@ -344,6 +291,2 @@ var id = name; | ||
/** | ||
* Generate a unique identifier based on a node. | ||
*/ | ||
Scope.prototype.generateUidIdentifierBasedOnNode = function generateUidIdentifierBasedOnNode(parent, defaultName) { | ||
@@ -425,12 +368,2 @@ var node = parent; | ||
/** | ||
* Determine whether evaluating the specific input `node` is a consequenceless reference. ie. | ||
* evaluating it wont result in potentially arbitrary code from being ran. The following are | ||
* whitelisted and determined not to cause side effects: | ||
* | ||
* - `this` expressions | ||
* - `super` expressions | ||
* - Bound identifiers | ||
*/ | ||
Scope.prototype.isStatic = function isStatic(node) { | ||
@@ -453,6 +386,2 @@ if (t.isThisExpression(node) || t.isSuper(node)) { | ||
/** | ||
* Possibly generate a memoised identifier if it is not static and has consequences. | ||
*/ | ||
Scope.prototype.maybeGenerateMemoised = function maybeGenerateMemoised(node, dontPush) { | ||
@@ -469,6 +398,4 @@ if (this.isStatic(node)) { | ||
Scope.prototype.checkBlockScopedCollisions = function checkBlockScopedCollisions(local, kind, name, id) { | ||
// ignore parameters | ||
if (kind === "param") return; | ||
// ignore hoisted functions if there's also a local let | ||
if (kind === "hoisted" && local.kind === "let") return; | ||
@@ -478,6 +405,4 @@ | ||
// don't allow duplicate bindings to exist alongside | ||
if (!duplicate) duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module"; | ||
// don't allow a local of param with a kind of let | ||
if (!duplicate) duplicate = local.kind === "param" && (kind === "let" || kind === "const"); | ||
@@ -547,3 +472,2 @@ | ||
helperName = "slicedToArray"; | ||
// TODO if (this.hub.file.isLoose("es6.forOf")) helperName += "-loose"; | ||
} | ||
@@ -668,4 +592,2 @@ return t.callExpression(file.addHelper(helperName), args); | ||
if (local) { | ||
// same identifier so continue safely as we're likely trying to register it | ||
// multiple times | ||
if (local.identifier === _id3) continue; | ||
@@ -676,5 +598,2 @@ | ||
// It's erroneous that we currently consider flow a binding, however, we can't | ||
// remove it because people might be depending on it. See warning section | ||
// in `warnOnFlowBinding`. | ||
if (local && local.path.isFlow()) local = null; | ||
@@ -808,6 +727,2 @@ | ||
/** | ||
* Set some arbitrary data on the current scope. | ||
*/ | ||
Scope.prototype.setData = function setData(key, val) { | ||
@@ -817,6 +732,2 @@ return this.data[key] = val; | ||
/** | ||
* Recursively walk up scope tree looking for the data `key`. | ||
*/ | ||
Scope.prototype.getData = function getData(key) { | ||
@@ -830,7 +741,2 @@ var scope = this; | ||
/** | ||
* Recursively walk up scope tree looking for the data `key` and if it exists, | ||
* remove it. | ||
*/ | ||
Scope.prototype.removeData = function removeData(key) { | ||
@@ -857,4 +763,2 @@ var scope = this; | ||
// | ||
this.references = (0, _create2.default)(null); | ||
@@ -866,4 +770,2 @@ this.bindings = (0, _create2.default)(null); | ||
// ForStatement - left, init | ||
if (path.isLoop()) { | ||
@@ -889,4 +791,2 @@ for (var _iterator14 = t.FOR_INIT_KEYS, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : (0, _getIterator3.default)(_iterator14);;) { | ||
// FunctionExpression - id | ||
if (path.isFunctionExpression() && path.has("id")) { | ||
@@ -898,4 +798,2 @@ if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { | ||
// Class | ||
if (path.isClassExpression() && path.has("id")) { | ||
@@ -907,4 +805,2 @@ if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { | ||
// Function - params, rest | ||
if (path.isFunction()) { | ||
@@ -930,4 +826,2 @@ var params = path.get("params"); | ||
// CatchClause - param | ||
if (path.isCatchClause()) { | ||
@@ -937,4 +831,2 @@ this.registerBinding("let", path); | ||
// Program | ||
var parent = this.getProgramParent(); | ||
@@ -953,3 +845,2 @@ if (parent.crawling) return; | ||
// register assignments | ||
for (var _iterator16 = state.assignments, _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : (0, _getIterator3.default)(_iterator16);;) { | ||
@@ -969,3 +860,2 @@ var _ref17; | ||
// register undeclared bindings as globals | ||
var ids = _path.getBindingIdentifiers(); | ||
@@ -980,7 +870,5 @@ var programParent = void 0; | ||
// register as constant violation | ||
_path.scope.registerConstantViolation(_path); | ||
} | ||
// register references | ||
for (var _iterator17 = state.references, _isArray17 = Array.isArray(_iterator17), _i17 = 0, _iterator17 = _isArray17 ? _iterator17 : (0, _getIterator3.default)(_iterator17);;) { | ||
@@ -1008,3 +896,2 @@ var _ref18; | ||
// register constant violations | ||
for (var _iterator18 = state.constantViolations, _isArray18 = Array.isArray(_iterator18), _i18 = 0, _iterator18 = _isArray18 ? _iterator18 : (0, _getIterator3.default)(_iterator18);;) { | ||
@@ -1068,6 +955,2 @@ var _ref19; | ||
/** | ||
* Walk up to the top of the scope tree and get the `Program`. | ||
*/ | ||
Scope.prototype.getProgramParent = function getProgramParent() { | ||
@@ -1083,7 +966,2 @@ var scope = this; | ||
/** | ||
* Walk up the scope tree until we hit either a Function or reach the | ||
* very top and hit Program. | ||
*/ | ||
Scope.prototype.getFunctionParent = function getFunctionParent() { | ||
@@ -1099,7 +977,2 @@ var scope = this; | ||
/** | ||
* Walk up the scope tree until we hit either a BlockStatement/Loop/Program/Function/Switch or reach the | ||
* very top and hit Program. | ||
*/ | ||
Scope.prototype.getBlockParent = function getBlockParent() { | ||
@@ -1115,6 +988,2 @@ var scope = this; | ||
/** | ||
* Walks the scope tree and gathers **all** bindings. | ||
*/ | ||
Scope.prototype.getAllBindings = function getAllBindings() { | ||
@@ -1132,6 +1001,2 @@ var ids = (0, _create2.default)(null); | ||
/** | ||
* Walks the scope tree and gathers all declarations of `kind`. | ||
*/ | ||
Scope.prototype.getAllBindingsOfKind = function getAllBindingsOfKind() { | ||
@@ -1219,6 +1084,2 @@ var ids = (0, _create2.default)(null); | ||
/** | ||
* Move a binding of `name` to another `scope`. | ||
*/ | ||
Scope.prototype.moveBindingTo = function moveBindingTo(name, scope) { | ||
@@ -1238,3 +1099,2 @@ var info = this.getBinding(name); | ||
Scope.prototype.removeBinding = function removeBinding(name) { | ||
// clear literal binding | ||
var info = this.getBinding(name); | ||
@@ -1245,3 +1105,2 @@ if (info) { | ||
// clear uids with this name - https://github.com/babel/babel/issues/2101 | ||
var scope = this; | ||
@@ -1248,0 +1107,0 @@ do { |
@@ -56,8 +56,5 @@ "use strict"; | ||
// build specifiers that point back to this export declaration | ||
var isDefault = exportDeclar.isExportDefaultDeclaration(); | ||
if (isDefault && (parentDeclar.isFunctionDeclaration() || parentDeclar.isClassDeclaration()) && !parentDeclar.node.id) { | ||
// Ensure that default class and function exports have a name so they have a identifier to | ||
// reference from the export specifier list. | ||
parentDeclar.node.id = parentDeclar.scope.generateUidIdentifier("default"); | ||
@@ -77,3 +74,2 @@ } | ||
// hoist to the top if it's a function | ||
if (parentDeclar.isFunctionDeclaration()) { | ||
@@ -88,6 +84,4 @@ aliasDeclar._blockHoist = 3; | ||
Renamer.prototype.maybeConvertFromClassFunctionDeclaration = function maybeConvertFromClassFunctionDeclaration(path) { | ||
return; // TODO | ||
return; | ||
// retain the `name` of a class/function declaration | ||
if (!path.isFunctionDeclaration() && !path.isClassDeclaration()) return; | ||
@@ -103,6 +97,4 @@ if (this.binding.kind !== "hoisted") return; | ||
Renamer.prototype.maybeConvertFromClassFunctionExpression = function maybeConvertFromClassFunctionExpression(path) { | ||
return; // TODO | ||
return; | ||
// retain the `name` of a class/function expression | ||
if (!path.isFunctionExpression() && !path.isClassExpression()) return; | ||
@@ -143,6 +135,3 @@ if (this.binding.kind !== "local") return; | ||
if (binding.type === "hoisted") { | ||
// https://github.com/babel/babel/issues/2435 | ||
// todo: hoist and convert function to a let | ||
} | ||
if (binding.type === "hoisted") {} | ||
@@ -149,0 +138,0 @@ if (parentDeclar) { |
@@ -41,18 +41,2 @@ "use strict"; | ||
/** | ||
* explode() will take a visitor object with all of the various shorthands | ||
* that we support, and validates & normalizes it into a common format, ready | ||
* to be used in traversal | ||
* | ||
* The various shorthands are: | ||
* * `Identifier() { ... }` -> `Identifier: { enter() { ... } }` | ||
* * `"Identifier|NumericLiteral": { ... }` -> `Identifier: { ... }, NumericLiteral: { ... }` | ||
* * Aliases in `babel-types`: e.g. `Property: { ... }` -> `ObjectProperty: { ... }, ClassProperty: { ... }` | ||
* | ||
* Other normalizations are: | ||
* * Visitors of virtual types are wrapped, so that they are only visited when | ||
* their dynamic check passes | ||
* * `enter` and `exit` functions are wrapped in arrays, to ease merging of | ||
* visitors | ||
*/ | ||
function explode(visitor) { | ||
@@ -62,3 +46,2 @@ if (visitor._exploded) return visitor; | ||
// normalise pipes | ||
for (var nodeType in visitor) { | ||
@@ -91,16 +74,10 @@ if (shouldIgnoreKey(nodeType)) continue; | ||
// verify data structure | ||
verify(visitor); | ||
// make sure there's no __esModule type since this is because we're using loose mode | ||
// and it sets __esModule to be enumerable on all modules :( | ||
delete visitor.__esModule; | ||
// ensure visitors are objects | ||
ensureEntranceObjects(visitor); | ||
// ensure enter/exit callbacks are arrays | ||
ensureCallbackArrays(visitor); | ||
// add type wrappers | ||
for (var _iterator2 = (0, _keys2.default)(visitor), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { | ||
@@ -125,3 +102,2 @@ var _ref2; | ||
// wrap all the functions | ||
var _fns2 = visitor[_nodeType3]; | ||
@@ -132,3 +108,2 @@ for (var type in _fns2) { | ||
// clear it from the visitor | ||
delete visitor[_nodeType3]; | ||
@@ -151,3 +126,2 @@ | ||
// merge the visitor if necessary or just put it back in | ||
if (visitor[_type]) { | ||
@@ -164,3 +138,2 @@ mergePair(visitor[_type], _fns2); | ||
// add aliases | ||
for (var _nodeType in visitor) { | ||
@@ -181,3 +154,2 @@ if (shouldIgnoreKey(_nodeType)) continue; | ||
// clear it from the visitor | ||
delete visitor[_nodeType]; | ||
@@ -239,3 +211,2 @@ | ||
if (visitorKey === "enter" || visitorKey === "exit") { | ||
// verify that it just contains functions | ||
validateVisitorMethods(nodeType + "." + visitorKey, visitors[visitorKey]); | ||
@@ -276,2 +247,3 @@ } else { | ||
var states = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; | ||
var wrapper = arguments[2]; | ||
@@ -289,4 +261,5 @@ var rootVisitor = {}; | ||
// if we have state then overload the callbacks to take it | ||
if (state) visitorType = wrapWithState(visitorType, state); | ||
if (state || wrapper) { | ||
visitorType = wrapWithStateOrWrapper(visitorType, state, wrapper); | ||
} | ||
@@ -301,18 +274,23 @@ var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {}; | ||
function wrapWithState(oldVisitor, state) { | ||
function wrapWithStateOrWrapper(oldVisitor, state, wrapper) { | ||
var newVisitor = {}; | ||
for (var key in oldVisitor) { | ||
var _loop = function _loop(key) { | ||
var fns = oldVisitor[key]; | ||
// not an enter/exit array of callbacks | ||
if (!Array.isArray(fns)) continue; | ||
if (!Array.isArray(fns)) return "continue"; | ||
fns = fns.map(function (fn) { | ||
var newFn = function newFn(path) { | ||
return fn.call(state, path, state); | ||
}; | ||
newFn.toString = function () { | ||
return fn.toString(); | ||
}; | ||
var newFn = fn; | ||
if (state) { | ||
newFn = function newFn(path) { | ||
return fn.call(state, path, state); | ||
}; | ||
} | ||
if (wrapper) { | ||
newFn = wrapper(state.key, key, newFn); | ||
} | ||
return newFn; | ||
@@ -322,2 +300,8 @@ }); | ||
newVisitor[key] = fns; | ||
}; | ||
for (var key in oldVisitor) { | ||
var _ret = _loop(key); | ||
if (_ret === "continue") continue; | ||
} | ||
@@ -357,9 +341,6 @@ | ||
function shouldIgnoreKey(key) { | ||
// internal/hidden key | ||
if (key[0] === "_") return true; | ||
// ignore function keys | ||
if (key === "enter" || key === "exit" || key === "shouldSkip") return true; | ||
// ignore other options | ||
if (key === "blacklist" || key === "noScope" || key === "skipKeys") return true; | ||
@@ -366,0 +347,0 @@ |
{ | ||
"name": "babel-traverse", | ||
"version": "6.13.0", | ||
"version": "6.14.0", | ||
"description": "", | ||
@@ -14,4 +14,4 @@ "author": "Sebastian McKenzie <sebmck@gmail.com>", | ||
"babel-runtime": "^6.9.0", | ||
"babel-types": "^6.13.0", | ||
"babylon": "^6.7.0", | ||
"babel-types": "^6.14.0", | ||
"babylon": "^6.9.0", | ||
"debug": "^2.2.0", | ||
@@ -18,0 +18,0 @@ "globals": "^8.3.0", |
146924
4132
Updatedbabel-types@^6.14.0
Updatedbabylon@^6.9.0