JS: Add CapturedVariableNode

This commit is contained in:
Asger Feldthaus
2020-04-07 19:02:46 +01:00
parent e5d3286ee9
commit 1f496d3c6b
2 changed files with 52 additions and 11 deletions

View File

@@ -317,6 +317,19 @@ class LocalVariable extends Variable {
else result = d.getContainer()
)
}
/**
* Gets the location of a declaration of this variable.
*
* If the variable has multiple declarations, an arbitrary one is used.
* If it has no declaration, the location of its declaring scope is used.
*/
Location getLocation() {
result = min(Location loc | loc = getADeclaration().getLocation() | loc order by loc.getStartLine(), loc.getStartColumn() )
or
not exists(getADeclaration()) and
result = getDeclaringContainer().getLocation()
}
}
/** A local variable that is not captured. */

View File

@@ -27,6 +27,7 @@ module DataFlow {
private newtype TNode =
TValueNode(AST::ValueNode nd) or
TSsaDefNode(SsaDefinition d) or
TCapturedVariableNode(LocalVariable v) { v.isCaptured() } or
TPropNode(@property p) or
TRestPatternNode(DestructuringPattern dp, Expr rest) { rest = dp.getRest() } or
TDestructuringPatternNode(DestructuringPattern dp) or
@@ -1221,6 +1222,29 @@ module DataFlow {
}
}
/**
* A data flow node representing a captured variable.
*/
private class CapturedVariableNode extends Node, TCapturedVariableNode {
LocalVariable variable;
CapturedVariableNode() { this = TCapturedVariableNode(variable) }
override BasicBlock getBasicBlock() {
result = variable.getDeclaringContainer().getStartBB()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
variable.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override string toString() {
result = variable.getName()
}
}
/**
* Gets the data flow node corresponding to `nd`.
*
@@ -1434,19 +1458,23 @@ module DataFlow {
or
immediateFlowStep(pred, succ)
or
// From an assignment or implicit initialization of a captured variable to its flow-insensitive node.
exists(SsaDefinition predDef |
pred = TSsaDefNode(predDef) and
succ = TCapturedVariableNode(predDef.getSourceVariable())
|
predDef instanceof SsaExplicitDefinition or
predDef instanceof SsaImplicitInit
)
or
// From a captured variable node to its flow-sensitive capture nodes
exists(SsaVariableCapture ssaCapture |
pred = TCapturedVariableNode(ssaCapture.getSourceVariable()) and
succ = TSsaDefNode(ssaCapture)
)
or
// Flow through implicit SSA nodes
exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) |
// from any explicit definition or implicit init of a captured variable into
// the capturing definition
exists(SsaSourceVariable v, SsaDefinition predDef |
v = ssa.(SsaVariableCapture).getSourceVariable() and
predDef.getSourceVariable() = v and
pred = TSsaDefNode(predDef)
|
predDef instanceof SsaExplicitDefinition or
predDef instanceof SsaImplicitInit
)
or
// from the inputs of phi and pi nodes into the node itself
pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition())
)