Merge pull request #14380 from asgerf/js/amd-range

JS: Add AmdModuleDefinition::Range
This commit is contained in:
Asger F
2023-10-05 21:05:28 +02:00
committed by GitHub
5 changed files with 45 additions and 15 deletions

View File

@@ -7,6 +7,34 @@ import javascript
private import semmle.javascript.internal.CachedStages
private import Expressions.ExprHasNoEffect
/**
* Companion module to the `AmdModuleDefinition` class.
*/
module AmdModuleDefinition {
/**
* A class that can be extended to treat calls as instances of `AmdModuleDefinition`.
*
* Subclasses should not depend on imports or `DataFlow::Node`.
*/
abstract class Range extends CallExpr { }
private class DefaultRange extends Range {
DefaultRange() {
inVoidContext(this) and
this.getCallee().(GlobalVarAccess).getName() = "define" and
exists(int n | n = this.getNumArgument() |
n = 1
or
n = 2 and this.getArgument(0) instanceof ArrayExpr
or
n = 3 and
this.getArgument(0) instanceof ConstantString and
this.getArgument(1) instanceof ArrayExpr
)
}
}
}
/**
* An AMD `define` call.
*
@@ -25,21 +53,7 @@ private import Expressions.ExprHasNoEffect
* where the first argument is the module name, the second argument an
* array of dependencies, and the third argument a factory method or object.
*/
class AmdModuleDefinition extends CallExpr {
AmdModuleDefinition() {
inVoidContext(this) and
this.getCallee().(GlobalVarAccess).getName() = "define" and
exists(int n | n = this.getNumArgument() |
n = 1
or
n = 2 and this.getArgument(0) instanceof ArrayExpr
or
n = 3 and
this.getArgument(0) instanceof ConstantString and
this.getArgument(1) instanceof ArrayExpr
)
}
class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range {
/** Gets the array of module dependencies, if any. */
ArrayExpr getDependencies() {
result = this.getArgument(0) or

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added the `AmdModuleDefinition::Range` class, making it possible to define custom aliases for the AMD `define` function.

View File

@@ -0,0 +1,3 @@
test.amd.range(function() {
return { foo: 42 };
});

View File

@@ -4,6 +4,7 @@ amoModule_exports
| lib/a.js:1:1:3:3 | <toplevel> | foo | lib/a.js:2:19:2:20 | 42 |
| lib/foo.js:1:1:4:0 | <toplevel> | foo | lib/foo.js:2:10:2:11 | 23 |
| lib/nested/a.js:1:1:3:3 | <toplevel> | foo | lib/nested/a.js:2:19:2:20 | 42 |
| test_range.js:1:1:4:0 | <toplevel> | foo | test_range.js:2:19:2:20 | 42 |
| tst2.js:1:1:3:3 | <toplevel> | foo | tst2.js:2:19:2:20 | 42 |
| tst3.js:1:1:3:3 | <toplevel> | foo | tst3.js:2:43:2:44 | 42 |
| tst4.js:1:1:11:3 | <toplevel> | bar | tst4.js:9:14:9:18 | b.bar |
@@ -22,6 +23,7 @@ amdModule
| lib/a.js:1:1:3:3 | <toplevel> | lib/a.js:1:1:3:2 | define( ... 2 };\\n}) |
| lib/foo.js:1:1:4:0 | <toplevel> | lib/foo.js:1:1:3:2 | define( ... : 23\\n}) |
| lib/nested/a.js:1:1:3:3 | <toplevel> | lib/nested/a.js:1:1:3:2 | define( ... 2 };\\n}) |
| test_range.js:1:1:4:0 | <toplevel> | test_range.js:1:1:3:2 | test.am ... 2 };\\n}) |
| tst2.js:1:1:3:3 | <toplevel> | tst2.js:1:1:3:2 | define( ... 42;\\n}) |
| tst3.js:1:1:3:3 | <toplevel> | tst3.js:1:1:3:2 | define( ... 42;\\n}) |
| tst4.js:1:1:11:3 | <toplevel> | tst4.js:1:1:11:2 | define( ... };\\n}) |
@@ -48,6 +50,7 @@ amdModuleDefinition
| lib/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/a.js:1:8:3:1 | functio ... 42 };\\n} |
| lib/foo.js:1:1:3:2 | define( ... : 23\\n}) | lib/foo.js:1:8:3:1 | {\\n foo: 23\\n} |
| lib/nested/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/nested/a.js:1:8:3:1 | functio ... 42 };\\n} |
| test_range.js:1:1:3:2 | test.am ... 2 };\\n}) | test_range.js:1:16:3:1 | functio ... 42 };\\n} |
| tst2.js:1:1:3:2 | define( ... 42;\\n}) | tst2.js:1:21:3:1 | functio ... = 42;\\n} |
| tst3.js:1:1:3:2 | define( ... 42;\\n}) | tst3.js:1:8:3:1 | functio ... = 42;\\n} |
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:6:11:11:1 | functio ... };\\n} |
@@ -78,6 +81,7 @@ amdModuleExportedSymbol
| lib/a.js:1:1:3:3 | <toplevel> | foo |
| lib/foo.js:1:1:4:0 | <toplevel> | foo |
| lib/nested/a.js:1:1:3:3 | <toplevel> | foo |
| test_range.js:1:1:4:0 | <toplevel> | foo |
| tst2.js:1:1:3:3 | <toplevel> | foo |
| tst3.js:1:1:3:3 | <toplevel> | foo |
| tst4.js:1:1:11:3 | <toplevel> | bar |
@@ -96,6 +100,7 @@ amdModuleExpr
| lib/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/a.js:2:12:2:22 | { foo: 42 } | lib/a.js:2:12:2:22 | { foo: 42 } |
| lib/foo.js:1:1:3:2 | define( ... : 23\\n}) | lib/foo.js:1:8:3:1 | {\\n foo: 23\\n} | lib/foo.js:1:8:3:1 | {\\n foo: 23\\n} |
| lib/nested/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/nested/a.js:2:12:2:22 | { foo: 42 } | lib/nested/a.js:2:12:2:22 | { foo: 42 } |
| test_range.js:1:1:3:2 | test.am ... 2 };\\n}) | test_range.js:2:12:2:22 | { foo: 42 } | test_range.js:2:12:2:22 | { foo: 42 } |
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:7:12:10:5 | {\\n ... r\\n } | tst4.js:7:12:10:5 | {\\n ... r\\n } |
| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:2:12:5:5 | {\\n ... r\\n } | tst5.js:2:12:5:5 | {\\n ... r\\n } |
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:2:12:5:5 | {\\n ... r\\n } | tst.js:2:12:5:5 | {\\n ... r\\n } |

View File

@@ -1,5 +1,9 @@
import javascript
class TestAmdModuleRange extends AmdModuleDefinition::Range {
TestAmdModuleRange() { this.getCallee().(PropAccess).getQualifiedName() = "test.amd.range" }
}
query predicate amoModule_exports(Module m, string name, DataFlow::Node exportValue) {
exportValue = m.getAnExportedValue(name)
}