@babel/traverse
Advanced tools
Comparing version 7.5.5 to 7.6.0
@@ -50,2 +50,53 @@ "use strict"; | ||
function completionRecordForSwitch(cases, paths) { | ||
let isLastCaseWithConsequent = true; | ||
for (let i = cases.length - 1; i >= 0; i--) { | ||
const switchCase = cases[i]; | ||
const consequent = switchCase.get("consequent"); | ||
let breakStatement; | ||
findBreak: for (const statement of consequent) { | ||
if (statement.isBlockStatement()) { | ||
for (const statementInBlock of statement.get("body")) { | ||
if (statementInBlock.isBreakStatement()) { | ||
breakStatement = statementInBlock; | ||
break findBreak; | ||
} | ||
} | ||
} else if (statement.isBreakStatement()) { | ||
breakStatement = statement; | ||
break; | ||
} | ||
} | ||
if (breakStatement) { | ||
while (breakStatement.key === 0 && breakStatement.parentPath.isBlockStatement()) { | ||
breakStatement = breakStatement.parentPath; | ||
} | ||
const prevSibling = breakStatement.getPrevSibling(); | ||
if (breakStatement.key > 0 && (prevSibling.isExpressionStatement() || prevSibling.isBlockStatement())) { | ||
paths = addCompletionRecords(prevSibling, paths); | ||
breakStatement.remove(); | ||
} else { | ||
breakStatement.replaceWith(breakStatement.scope.buildUndefinedNode()); | ||
paths = addCompletionRecords(breakStatement, paths); | ||
} | ||
} else if (isLastCaseWithConsequent) { | ||
const statementFinder = statement => !statement.isBlockStatement() || statement.get("body").some(statementFinder); | ||
const hasConsequent = consequent.some(statementFinder); | ||
if (hasConsequent) { | ||
paths = addCompletionRecords(consequent[consequent.length - 1], paths); | ||
isLastCaseWithConsequent = false; | ||
} | ||
} | ||
} | ||
return paths; | ||
} | ||
function getCompletionRecords() { | ||
@@ -66,5 +117,6 @@ let paths = []; | ||
paths = addCompletionRecords(this.get("handler"), paths); | ||
paths = addCompletionRecords(this.get("finalizer"), paths); | ||
} else if (this.isCatchClause()) { | ||
paths = addCompletionRecords(this.get("body"), paths); | ||
} else if (this.isSwitchStatement()) { | ||
paths = completionRecordForSwitch(this.get("cases"), paths); | ||
} else { | ||
@@ -71,0 +123,0 @@ paths.push(this); |
@@ -72,3 +72,3 @@ "use strict"; | ||
if (functions && status === "function") functions.push(violation); | ||
if (functions && status === "unknown") functions.push(violation); | ||
return status === "before"; | ||
@@ -75,0 +75,0 @@ }); |
@@ -175,30 +175,86 @@ "use strict"; | ||
function _guessExecutionStatusRelativeTo(target) { | ||
const targetFuncParent = target.scope.getFunctionParent() || target.scope.getProgramParent(); | ||
const selfFuncParent = this.scope.getFunctionParent() || target.scope.getProgramParent(); | ||
function getOuterFunction(path) { | ||
return (path.scope.getFunctionParent() || path.scope.getProgramParent()).path; | ||
} | ||
if (targetFuncParent.node !== selfFuncParent.node) { | ||
const status = this._guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent); | ||
function isExecutionUncertain(type, key) { | ||
switch (type) { | ||
case "LogicalExpression": | ||
return key === "right"; | ||
if (status) { | ||
return status; | ||
} else { | ||
target = targetFuncParent.path; | ||
case "ConditionalExpression": | ||
case "IfStatement": | ||
return key === "consequent" || key === "alternate"; | ||
case "WhileStatement": | ||
case "DoWhileStatement": | ||
case "ForInStatement": | ||
case "ForOfStatement": | ||
return key === "body"; | ||
case "ForStatement": | ||
return key === "body" || key === "update"; | ||
case "SwitchStatement": | ||
return key === "cases"; | ||
case "TryStatement": | ||
return key === "handler"; | ||
case "AssignmentPattern": | ||
return key === "right"; | ||
case "OptionalMemberExpression": | ||
return key === "property"; | ||
case "OptionalCallExpression": | ||
return key === "arguments"; | ||
default: | ||
return false; | ||
} | ||
} | ||
function isExecutionUncertainInList(paths, maxIndex) { | ||
for (let i = 0; i < maxIndex; i++) { | ||
const path = paths[i]; | ||
if (isExecutionUncertain(path.parent.type, path.parentKey)) { | ||
return true; | ||
} | ||
} | ||
const targetPaths = target.getAncestry(); | ||
if (targetPaths.indexOf(this) >= 0) return "after"; | ||
const selfPaths = this.getAncestry(); | ||
return false; | ||
} | ||
function _guessExecutionStatusRelativeTo(target) { | ||
const funcParent = { | ||
this: getOuterFunction(this), | ||
target: getOuterFunction(target) | ||
}; | ||
if (funcParent.target.node !== funcParent.this.node) { | ||
return this._guessExecutionStatusRelativeToDifferentFunctions(funcParent.target); | ||
} | ||
const paths = { | ||
target: target.getAncestry(), | ||
this: this.getAncestry() | ||
}; | ||
if (paths.target.indexOf(this) >= 0) return "after"; | ||
if (paths.this.indexOf(target) >= 0) return "before"; | ||
let commonPath; | ||
let targetIndex; | ||
let selfIndex; | ||
const commonIndex = { | ||
target: 0, | ||
this: 0 | ||
}; | ||
for (selfIndex = 0; selfIndex < selfPaths.length; selfIndex++) { | ||
const selfPath = selfPaths[selfIndex]; | ||
targetIndex = targetPaths.indexOf(selfPath); | ||
while (!commonPath && commonIndex.this < paths.this.length) { | ||
const path = paths.this[commonIndex.this]; | ||
commonIndex.target = paths.target.indexOf(path); | ||
if (targetIndex >= 0) { | ||
commonPath = selfPath; | ||
break; | ||
if (commonIndex.target >= 0) { | ||
commonPath = path; | ||
} else { | ||
commonIndex.this++; | ||
} | ||
@@ -208,45 +264,52 @@ } | ||
if (!commonPath) { | ||
return "before"; | ||
throw new Error("Internal Babel error - The two compared nodes" + " don't appear to belong to the same program."); | ||
} | ||
const targetRelationship = targetPaths[targetIndex - 1]; | ||
const selfRelationship = selfPaths[selfIndex - 1]; | ||
if (!targetRelationship || !selfRelationship) { | ||
return "before"; | ||
if (isExecutionUncertainInList(paths.this, commonIndex.this - 1) || isExecutionUncertainInList(paths.target, commonIndex.target - 1)) { | ||
return "unknown"; | ||
} | ||
if (targetRelationship.listKey && targetRelationship.container === selfRelationship.container) { | ||
return targetRelationship.key > selfRelationship.key ? "before" : "after"; | ||
const divergence = { | ||
this: paths.this[commonIndex.this - 1], | ||
target: paths.target[commonIndex.target - 1] | ||
}; | ||
if (divergence.target.listKey && divergence.this.listKey && divergence.target.container === divergence.this.container) { | ||
return divergence.target.key > divergence.this.key ? "before" : "after"; | ||
} | ||
const keys = t().VISITOR_KEYS[commonPath.type]; | ||
const targetKeyPosition = keys.indexOf(targetRelationship.key); | ||
const selfKeyPosition = keys.indexOf(selfRelationship.key); | ||
return targetKeyPosition > selfKeyPosition ? "before" : "after"; | ||
const keyPosition = { | ||
this: keys.indexOf(divergence.this.parentKey), | ||
target: keys.indexOf(divergence.target.parentKey) | ||
}; | ||
return keyPosition.target > keyPosition.this ? "before" : "after"; | ||
} | ||
function _guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent) { | ||
const targetFuncPath = targetFuncParent.path; | ||
if (!targetFuncPath.isFunctionDeclaration()) return; | ||
const binding = targetFuncPath.scope.getBinding(targetFuncPath.node.id.name); | ||
const executionOrderCheckedNodes = new WeakSet(); | ||
function _guessExecutionStatusRelativeToDifferentFunctions(target) { | ||
if (!target.isFunctionDeclaration()) return "unknown"; | ||
const binding = target.scope.getBinding(target.node.id.name); | ||
if (!binding.references) return "before"; | ||
const referencePaths = binding.referencePaths; | ||
let allStatus; | ||
for (const path of referencePaths) { | ||
const childOfFunction = !!path.find(path => path.node === target.node); | ||
if (childOfFunction) continue; | ||
if (path.key !== "callee" || !path.parentPath.isCallExpression()) { | ||
return; | ||
return "unknown"; | ||
} | ||
} | ||
let allStatus; | ||
if (executionOrderCheckedNodes.has(path.node)) continue; | ||
executionOrderCheckedNodes.add(path.node); | ||
for (const path of referencePaths) { | ||
const childOfFunction = !!path.find(path => path.node === targetFuncPath.node); | ||
if (childOfFunction) continue; | ||
const status = this._guessExecutionStatusRelativeTo(path); | ||
if (allStatus) { | ||
if (allStatus !== status) return; | ||
executionOrderCheckedNodes.delete(path.node); | ||
if (allStatus && allStatus !== status) { | ||
return "unknown"; | ||
} else { | ||
@@ -253,0 +316,0 @@ allStatus = status; |
@@ -463,7 +463,3 @@ "use strict"; | ||
buildUndefinedNode() { | ||
if (this.hasBinding("undefined")) { | ||
return t().unaryExpression("void", t().numericLiteral(0), true); | ||
} else { | ||
return t().identifier("undefined"); | ||
} | ||
return t().unaryExpression("void", t().numericLiteral(0), true); | ||
} | ||
@@ -470,0 +466,0 @@ |
{ | ||
"name": "@babel/traverse", | ||
"version": "7.5.5", | ||
"version": "7.6.0", | ||
"description": "The Babel Traverse module maintains the overall tree state, and is responsible for replacing, removing, and adding nodes", | ||
@@ -15,7 +15,7 @@ "author": "Sebastian McKenzie <sebmck@gmail.com>", | ||
"@babel/code-frame": "^7.5.5", | ||
"@babel/generator": "^7.5.5", | ||
"@babel/generator": "^7.6.0", | ||
"@babel/helper-function-name": "^7.1.0", | ||
"@babel/helper-split-export-declaration": "^7.4.4", | ||
"@babel/parser": "^7.5.5", | ||
"@babel/types": "^7.5.5", | ||
"@babel/parser": "^7.6.0", | ||
"@babel/types": "^7.6.0", | ||
"debug": "^4.1.0", | ||
@@ -28,3 +28,3 @@ "globals": "^11.1.0", | ||
}, | ||
"gitHead": "0407f034f09381b95e9cabefbf6b176c76485a43" | ||
"gitHead": "cbd5a26e57758e3f748174ff84aa570e8780e85d" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
148137
4375
Updated@babel/generator@^7.6.0
Updated@babel/parser@^7.6.0
Updated@babel/types@^7.6.0