JS: Add SsaExplicitDefinition.getRhsNode

This commit is contained in:
Asger F
2019-05-14 16:12:44 +01:00
parent 8b60314d85
commit c97b9af4b8
5 changed files with 95 additions and 0 deletions

View File

@@ -521,6 +521,27 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
) {
getDef().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/**
* Gets the data flow node representing the incoming value assigned at this definition,
* if any.
*/
DataFlow::Node getRhsNode() {
exists(VarDef def | def = getDef() |
result = def.getSource().flow()
or
exists(VarRef ref |
ref = getSourceVariable().getAReference() and
def.getTarget().(BindingPattern).getABindingVarRef() = ref and
result = DataFlow::patternPropRead(ref)
)
or
result = DataFlow::parameterNode(def)
or
// Handle class, function, namespace, and enum declaration statement
result.getAstNode() = def.(Stmt)
)
}
}
/**

View File

@@ -1089,6 +1089,27 @@ module DataFlow {
nd = TExceptionalFunctionReturnNode(function)
}
/**
* INTERNAL. DO NOT USE.
*
* Gets the `PropRead` node corresponding to the value stored in the given
* binding pattern due to destructuring.
*
* For example, in `let { p: value } = f()`, the `value` pattern maps to a `PropRead`
* extracting the `p` property.
*/
DataFlow::PropRead patternPropRead(BindingPattern value) {
exists(PropertyPattern prop |
value = prop.getValuePattern() and
result = TPropNode(prop)
)
or
exists(ArrayPattern array |
value = array.getAnElement() and
result = TElementPatternNode(array, value)
)
}
/**
* A classification of flows that are not modeled, or only modeled incompletely, by
* `DataFlowNode`:

View File

@@ -0,0 +1,14 @@
| tst.js:2:7:2:13 | a = g() | a | tst.js:2:11:2:13 | g() |
| tst.js:4:7:4:24 | { propB: b } = g() | b | tst.js:4:9:4:16 | propB: b |
| tst.js:6:7:6:34 | { propC ... } = g() | c | tst.js:6:9:6:16 | propC: c |
| tst.js:6:7:6:34 | { propC ... } = g() | d | tst.js:6:19:6:26 | propD: d |
| tst.js:8:7:8:41 | { array ... } = g() | elm1 | tst.js:8:22:8:25 | elm1 |
| tst.js:8:7:8:41 | { array ... } = g() | elm2 | tst.js:8:28:8:31 | elm2 |
| tst.js:17:3:17:22 | ({ propB: b }) = g() | b | tst.js:17:6:17:13 | propB: b |
| tst.js:19:3:19:32 | ({ prop ... ) = g() | c | tst.js:19:6:19:13 | propC: c |
| tst.js:19:3:19:32 | ({ prop ... ) = g() | d | tst.js:19:16:19:23 | propD: d |
| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm1 | tst.js:21:5:21:8 | elm1 |
| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm2 | tst.js:21:11:21:14 | elm2 |
| tst.js:31:12:31:23 | [elm1, elm2] | elm1 | tst.js:31:13:31:16 | elm1 |
| tst.js:31:12:31:23 | [elm1, elm2] | elm2 | tst.js:31:19:31:22 | elm2 |
| tst.js:31:26:31:40 | { prop: value } | value | tst.js:31:28:31:38 | prop: value |

View File

@@ -0,0 +1,4 @@
import javascript
from SsaExplicitDefinition def
select def, def.getSourceVariable(), def.getRhsNode()

View File

@@ -0,0 +1,35 @@
function f() {
let a = g();
let { propB: b } = g();
let { propC: c, propD: d } = g();
let { arrayProp: [ elm1, elm2 ] } = g();
a; // Ensure variables are live.
b;
c;
d;
elm1;
elm2;
({ propB: b }) = g();
({ propC: c, propD: d }) = g();
[ elm1, elm2 ] = g();
a;
b;
c;
d;
elm1;
elm2;
}
function h([elm1, elm2], { prop: value }) {
elm1;
elm2;
value;
}