Skip to content

Commit 61f6580

Browse files
committed
add API in PackageExports.qll for getting a value exported under a name
1 parent d3653b3 commit 61f6580

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

javascript/ql/src/semmle/javascript/PackageExports.qll

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) {
4040
exists(DataFlow::SourceNode callee |
4141
callee = getAValueExportedBy(packageJSON).(DataFlow::NewNode).getCalleeNode().getALocalSource()
4242
|
43-
result = callee.getAPropertyRead("prototype").getAPropertyWrite()
43+
result = callee.getAPropertyRead("prototype").getAPropertyWrite().getRhs()
4444
or
4545
result = callee.(DataFlow::ClassNode).getAnInstanceMethod()
4646
)
@@ -68,10 +68,22 @@ DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) {
6868
private DataFlow::Node getAnExportFromModule(Module mod) {
6969
result.analyze().getAValue() = mod.(NodeModule).getAModuleExportsValue()
7070
or
71-
exists(ASTNode export | result.getEnclosingExpr() = export | mod.exports(_, export))
71+
result = getAnExportedValue(mod, _)
72+
}
73+
74+
/**
75+
* Gets a value exported from `mod` under `name`.
76+
*/
77+
DataFlow::Node getAnExportedValue(Module mod, string name) {
78+
exists(Property export | result.asExpr() = export.getInit() | mod.exports(name, export))
79+
or
80+
result =
81+
DataFlow::valueNode(any(ASTNode export | mod.exports(name, export)))
82+
.(DataFlow::PropWrite)
83+
.getRhs()
7284
or
7385
exists(ExportDeclaration export |
74-
result = export.getSourceNode(_) and
75-
mod = export.getTopLevel()
86+
result = export.getSourceNode(name) and
87+
mod = export.getEnclosingModule()
7688
)
7789
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
// not imported from anywhere
3+
foo: function foo() {},
4+
bar: function bar() {}
5+
}

javascript/ql/test/library-tests/PackageExports/tests.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@ getAValueExportedBy
3434
| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:0 | this |
3535
| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:73 | module. ... rt() {} |
3636
| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:18:1:73 | functio ... rt() {} |
37+
getAnExportedValue
38+
| absent_main/index.js:1:1:2:0 | <toplevel> | foo | absent_main/index.js:1:22:1:34 | function() {} |
39+
| esmodules/main.js:1:1:4:0 | <toplevel> | exported | esmodules/main.js:1:8:1:29 | functio ... ed() {} |
40+
| lib1/baz.js:1:1:5:1 | <toplevel> | bar | lib1/baz.js:4:10:4:26 | function bar() {} |
41+
| lib1/baz.js:1:1:5:1 | <toplevel> | foo | lib1/baz.js:3:10:3:26 | function foo() {} |
42+
| lib1/foo.js:1:1:3:47 | <toplevel> | foo | lib1/foo.js:3:22:3:47 | functio ... ed() {} |
43+
| lib1/main.js:1:1:17:30 | <toplevel> | Baz | lib1/main.js:17:22:17:30 | new Baz() |
44+
| lib1/main.js:1:1:17:30 | <toplevel> | bar | lib1/main.js:5:22:9:1 | class B ... () {}\\n} |
45+
| lib1/main.js:1:1:17:30 | <toplevel> | foo | lib1/main.js:3:22:3:40 | require("./foo.js") |

javascript/ql/test/library-tests/PackageExports/tests.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ query PackageJSON getTopmostPackageJSON() { result = Exports::getTopmostPackageJ
66
query DataFlow::Node getAValueExportedBy(PackageJSON json) {
77
result = Exports::getAValueExportedBy(json)
88
}
9+
10+
query DataFlow::Node getAnExportedValue(Module mod, string name) {
11+
result = Exports::getAnExportedValue(mod, name)
12+
}

0 commit comments

Comments
 (0)