44
55import javascript
66
7+ deprecated
78module GlobalAccessPath {
9+ /**
10+ * DEPRECATED. Instead use `AccessPath::getAReferenceTo` with the result and parameter reversed.
11+ */
12+ pragma [ inline]
13+ string fromReference ( DataFlow:: Node node ) {
14+ node = AccessPath:: getAReferenceTo ( result )
15+ }
16+
17+ /**
18+ * DEPRECATED. Instead use `AccessPath::getAnAssignmentTo` with the result and parameter reversed.
19+ */
20+ pragma [ inline]
21+ string fromRhs ( DataFlow:: Node node ) {
22+ node = AccessPath:: getAnAssignmentTo ( result )
23+ }
24+
25+ /**
26+ * DEPRECATED. Use `AccessPath::getAReferenceOrAssignmentTo`.
27+ */
28+ pragma [ inline]
29+ string getAccessPath ( DataFlow:: Node node ) {
30+ result = fromReference ( node )
31+ or
32+ not exists ( fromReference ( node ) ) and
33+ result = fromRhs ( node )
34+ }
35+ }
36+
37+ module AccessPath {
838 /**
939 * A source node that can be the root of an access path.
1040 */
11- private class Root extends DataFlow:: SourceNode {
41+ class Root extends DataFlow:: SourceNode {
1242 Root ( ) {
1343 not this .accessesGlobal ( _) and
1444 not this instanceof DataFlow:: PropRead and
@@ -53,7 +83,7 @@ module GlobalAccessPath {
5383 * ```
5484 */
5585 cached
56- string fromReference ( DataFlow:: Node node , Root root ) {
86+ private string fromReference ( DataFlow:: Node node , Root root ) {
5787 root = node and
5888 not root .isGlobal ( ) and
5989 result = ""
@@ -110,29 +140,6 @@ module GlobalAccessPath {
110140 )
111141 }
112142
113- /**
114- * Gets the global access path referred to by `node`.
115- *
116- * This holds for direct references as well as for aliases
117- * established through local data flow.
118- *
119- * Examples:
120- * ```
121- * function f() {
122- * let v = foo.bar; // reference to 'foo.bar'
123- * v.baz; // reference to 'foo.bar.baz'
124- * }
125- *
126- * (function(ns) {
127- * ns.x; // reference to 'NS.x'
128- * })(NS = NS || {});
129- * ```
130- */
131- cached
132- string fromReference ( DataFlow:: Node node ) {
133- result = fromReference ( node , DataFlow:: globalAccessPathRootPseudoNode ( ) )
134- }
135-
136143 /**
137144 * Holds if `rhs` is the right-hand side of a self-assignment.
138145 *
@@ -183,7 +190,7 @@ module GlobalAccessPath {
183190 * ```
184191 */
185192 cached
186- string fromRhs ( DataFlow:: Node node , Root root ) {
193+ private string fromRhs ( DataFlow:: Node node , Root root ) {
187194 exists ( DataFlow:: PropWrite write , string baseName |
188195 node = write .getRhs ( ) and
189196 result = baseName + "." + write .getPropertyName ( )
@@ -225,42 +232,109 @@ module GlobalAccessPath {
225232 }
226233
227234 /**
228- * Gets the global access path `node` is being assigned to, if any.
235+ * Gets a node that refers to the given access path relative to the given `root` node,
236+ * or `root` itself if the access path is empty.
229237 *
230- * Only holds for the immediate right-hand side of an assignment or property, not
231- * for nodes that transitively flow there.
238+ * This works for direct references as well as for aliases established through local data flow.
239+ *
240+ * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`.
232241 *
233- * For example, the class nodes below all map to `foo.bar` :
242+ * For example:
234243 * ```
235- * foo.bar = class {};
244+ * function f(x) {
245+ * let a = x.f.g; // reference to (x, ".f.g")
246+ * let b = a.h; // reference to (x, ".f.g.h")
247+ * }
248+ * ```
249+ */
250+ DataFlow:: Node getAReferenceTo ( Root root , string path ) {
251+ path = fromReference ( result , root ) and
252+ not root .isGlobal ( )
253+ }
254+
255+ /**
256+ * Gets a node that refers to the given global access path.
236257 *
237- * foo = { bar: class {} };
258+ * This works for direct references as well as for aliases established through local data flow.
259+ *
260+ * Examples:
261+ * ```
262+ * function f() {
263+ * let v = foo.bar; // reference to 'foo.bar'
264+ * v.baz; // reference to 'foo.bar.baz'
265+ * }
266+ *
267+ * (function(ns) {
268+ * ns.x; // reference to 'NS.x'
269+ * })(NS = NS || {});
270+ * ```
271+ */
272+ DataFlow:: Node getAReferenceTo ( string path ) {
273+ path = fromReference ( result , DataFlow:: globalAccessPathRootPseudoNode ( ) )
274+ }
275+
276+ /**
277+ * Gets a node that is assigned to the given access path relative to the given `root` node.
278+ *
279+ * Only gets the immediate right-hand side of an assignment or property, not
280+ * nodes that transitively flow there.
281+ *
282+ * Note that access paths contain an initial `.`, such as in `.foo.bar`.
238283 *
284+ * For example, the class nodes below are all assignments to `(x, ".foo.bar")`.
285+ * ```
286+ * function f(x) {
287+ * x.foo.bar = class {};
288+ * x.foo = { bar: class() };
289+ * let alias = x;
290+ * alias.foo.bar = class {};
291+ * }
292+ * ```
293+ */
294+ DataFlow:: Node getAnAssignmentTo ( Root root , string path ) {
295+ path = fromRhs ( result , root ) and
296+ not root .isGlobal ( )
297+ }
298+
299+ /**
300+ * Gets a node that is assigned to the given global access path.
301+ *
302+ * Only gets the immediate right-hand side of an assignment or property or a global declaration,
303+ * not nodes that transitively flow there.
304+ *
305+ * For example, the class nodes below are all assignmetns to `foo.bar`:
306+ * ```
307+ * foo.bar = class {};
308+ * foo = { bar: class {} };
239309 * (function(f) {
240310 * f.bar = class {}
241311 * })(foo = foo || {});
242312 * ```
243313 */
244- cached
245- string fromRhs ( DataFlow:: Node node ) {
246- result = fromRhs ( node , DataFlow:: globalAccessPathRootPseudoNode ( ) )
314+ DataFlow:: Node getAnAssignmentTo ( string path ) {
315+ path = fromRhs ( result , DataFlow:: globalAccessPathRootPseudoNode ( ) )
247316 }
248317
249318 /**
250- * Gets the access path relative to `root` referenced by or assigned to `node`.
319+ * Gets a node that refers to or is assigned to the given global access path.
320+ *
321+ * See `getAReferenceTo` and `getAnAssignmentTo` for more details.
251322 */
252- string getAccessPath ( DataFlow:: Node node , Root root ) {
253- result = fromReference ( node , root )
323+ DataFlow:: Node getAReferenceOrAssignmentTo ( string path ) {
324+ result = getAReferenceTo ( path )
254325 or
255- not exists ( fromReference ( node , root ) ) and
256- result = fromRhs ( node , root )
326+ result = getAnAssignmentTo ( path )
257327 }
258328
259329 /**
260- * Gets the global access path referenced by or assigned to `node`.
330+ * Gets a node that refers to or is assigned to the given access path.
331+ *
332+ * See `getAReferenceTo` and `getAnAssignmentTo` for more details.
261333 */
262- string getAccessPath ( DataFlow:: Node node ) {
263- result = getAccessPath ( node , DataFlow:: globalAccessPathRootPseudoNode ( ) )
334+ DataFlow:: Node getAReferenceOrAssignmentTo ( Root root , string path ) {
335+ result = getAReferenceTo ( root , path )
336+ or
337+ result = getAnAssignmentTo ( root , path )
264338 }
265339
266340 /**
@@ -269,14 +343,13 @@ module GlobalAccessPath {
269343 pragma [ inline]
270344 predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
271345 exists ( string name , Root root |
272- name = fromRhs ( pred , root ) and
273- name = fromReference ( succ , root ) and
274- not root .isGlobal ( )
346+ pred = getAnAssignmentTo ( root , name ) and
347+ succ = getAReferenceTo ( root , name )
275348 )
276349 or
277350 exists ( string name |
278- name = fromRhs ( pred ) and
279- name = fromReference ( succ ) and
351+ pred = getAnAssignmentTo ( name ) and
352+ succ = getAReferenceTo ( name ) and
280353 isAssignedInUniqueFile ( name )
281354 )
282355 }
0 commit comments