Module SSA
Provides classes for working with static single assignment form (SSA).
We compute SSA form based on the intra-procedural CFG, without
any call graph information. This means that we have to make worst-case
assumptions about the possible effects of function calls and yield:
- For a variable
xdeclared in a functionf, ifxhas assignments in a function other thanf, then any function call andyieldexpression is assumed to writex. - If
xis not written outsidef, then function calls can never affectx, whileyieldexpressions in functions other thanfstill may affect it.
This is modeled as follows.
Within each function g that accesses a variable x declared in an
enclosing function f, we introduce a pseudo-assignment to x called
a capture of x at the beginning of g that (conceptually) captures
the current value of x.
Additionally, we introduce re-captures for x in the following
places:
- At any function call and
yield, ifxis assigned outsidef. - At any
yieldoutsidef, ifxis not assigned outsidef.
Re-captures are introduced only where needed, that is, where there
is a live use of x after the re-capture.
To see why re-captures need to be placed at yield expressions,
consider the following function:
function k() {
var x = 0;
function* iter() {
console.log(x);
yield;
console.log(x);
}
var gen = iter();
gen.next();
++x;
gen.next();
}
Here, iter has a capture for x at its beginning, and a re-capture
at the yield to reflect the fact that x is incremented between the
two console.log calls.
In the above example, x is only assigned inside its declaring function
k, so function calls and yield expressions inside k cannot affect it.
Consider another example:
function* k() {
var x = 0;
console.log(x);
yield () => ++x;
console.log(x);
}
var gen = k();
gen.next().value();
gen.next();
Here, x is assigned outside its declaring function k, so the yield
expression in k induces a re-capture of x to reflect the fact that x
is incremented between the two console.log calls.
Import path
import semmle.javascript.SSAImports
| javascript | Provides classes for working with JavaScript programs, as well as JSON, YAML and HTML. |
Classes
| SsaDefinition | An SSA definition. |
| SsaExplicitDefinition | An SSA definition that corresponds to an explicit assignment or other variable definition. |
| SsaImplicitDefinition | An SSA definition that does not correspond to an explicit variable definition. |
| SsaImplicitInit | An SSA definition representing the implicit initialization of a variable at the beginning of its scope. |
| SsaPhiNode | An SSA phi node, that is, a pseudo-definition for a variable at a point in the flow graph where otherwise two or more definitions for the variable would be visible. |
| SsaPseudoDefinition | An SSA definition that has no actual semantics, but simply serves to merge or filter data flow. |
| SsaRefinementNode | A refinement node, that is, a pseudo-definition for a variable at a point in the flow graph where additional information about this variable becomes available that may restrict its possible set of values. |
| SsaSourceVariable | A variable that can be SSA converted, that is, a local variable. |
| SsaVariable | An SSA variable. |
| SsaVariableCapture | An SSA definition representing the capturing of an SSA-convertible variable in the closure of a nested function. |