Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 939eab2

Browse files
committed
JS: refactor expressions to dataflow nodes
1 parent 8d78731 commit 939eab2

1 file changed

Lines changed: 51 additions & 64 deletions

File tree

javascript/ql/src/semmle/javascript/Closure.qll

Lines changed: 51 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,100 +6,77 @@ import javascript
66

77
module Closure {
88
/**
9-
* A call to a function in the `goog` namespace such as `goog.provide` or `goog.load`.
9+
* A reference to a Closure namespace.
1010
*/
11-
class GoogFunctionCall extends CallExpr {
12-
GoogFunctionCall() {
13-
exists(GlobalVariable gv | gv.getName() = "goog" |
14-
this.getCallee().(DotExpr).getBase() = gv.getAnAccess()
15-
)
16-
}
17-
18-
/** Gets the name of the invoked function. */
19-
string getFunctionName() { result = getCallee().(DotExpr).getPropertyName() }
11+
abstract class ClosureNamespaceRef extends DataFlow::Node {
12+
/**
13+
* Gets the namespace being referenced.
14+
*/
15+
abstract string getClosureNamespace();
2016
}
2117

2218
/**
23-
* An expression statement consisting of a call to a function
24-
* in the `goog` namespace.
19+
* A call to a method on the `goog.` namespace, as a closure reference.
2520
*/
26-
class GoogFunctionCallStmt extends ExprStmt {
27-
GoogFunctionCallStmt() { super.getExpr() instanceof GoogFunctionCall }
28-
29-
override GoogFunctionCall getExpr() { result = super.getExpr() }
21+
abstract private class DefaultNamespaceRef extends DataFlow::MethodCallNode, ClosureNamespaceRef {
22+
DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() }
3023

31-
/** Gets the name of the invoked function. */
32-
string getFunctionName() { result = getExpr().getFunctionName() }
33-
34-
/** Gets the `i`th argument to the invoked function. */
35-
Expr getArgument(int i) { result = getExpr().getArgument(i) }
36-
37-
/** Gets an argument to the invoked function. */
38-
Expr getAnArgument() { result = getArgument(_) }
24+
override string getClosureNamespace() { result = getArgument(0).asExpr().getStringValue() }
3925
}
4026

41-
abstract private class GoogNamespaceRef extends ExprOrStmt { abstract string getClosureNamespace(); }
42-
4327
/**
44-
* A call to `goog.provide`.
28+
* Holds if `node` is the dataflow node for a top-level expression.
4529
*/
46-
class GoogProvide extends GoogFunctionCallStmt, GoogNamespaceRef {
47-
GoogProvide() { getFunctionName() = "provide" }
48-
49-
/** Gets the identifier of the namespace created by this call. */
50-
override string getClosureNamespace() { result = getArgument(0).getStringValue() }
30+
private predicate isTopLevelExpr(DataFlow::Node node) {
31+
node.getTopLevel().getAChildStmt().(ExprStmt).getExpr().flow() = node
5132
}
5233

5334
/**
54-
* A call to `goog.require`.
35+
* A top-level call to `goog.provide`.
5536
*/
56-
class GoogRequire extends GoogFunctionCall, GoogNamespaceRef {
57-
GoogRequire() { getFunctionName() = "require" }
58-
59-
/** Gets the identifier of the namespace imported by this call. */
60-
override string getClosureNamespace() { result = getArgument(0).getStringValue() }
37+
class ClosureProvideCall extends DefaultNamespaceRef {
38+
ClosureProvideCall() {
39+
getMethodName() = "provide" and
40+
isTopLevelExpr(this)
41+
}
6142
}
6243

63-
private class GoogRequireImport extends GoogRequire, Import {
64-
/** Gets the module in which this import appears. */
65-
override Module getEnclosingModule() { result = getTopLevel() }
66-
67-
/** Gets the (unresolved) path that this import refers to. */
68-
override PathExpr getImportedPath() { result = getArgument(0) }
44+
/**
45+
* A call to `goog.require`.
46+
*/
47+
class ClosureRequireCall extends DefaultNamespaceRef {
48+
ClosureRequireCall() { getMethodName() = "require" }
6949
}
7050

7151
/**
72-
* A call to `goog.module` or `goog.declareModuleId`.
52+
* A top-level call to `goog.module` or `goog.declareModuleId`.
7353
*/
74-
class GoogModuleDeclaration extends GoogFunctionCallStmt, GoogNamespaceRef {
75-
GoogModuleDeclaration() {
76-
getFunctionName() = "module" or
77-
getFunctionName() = "declareModuleId"
54+
class ClosureModuleDeclaration extends DefaultNamespaceRef {
55+
ClosureModuleDeclaration() {
56+
(getMethodName() = "module" or getMethodName() = "declareModuleId") and
57+
isTopLevelExpr(this)
7858
}
79-
80-
/** Gets the identifier of the namespace imported by this call. */
81-
override string getClosureNamespace() { result = getArgument(0).getStringValue() }
8259
}
8360

8461
/**
8562
* A module using the Closure module system, declared using `goog.module()` or `goog.declareModuleId()`.
8663
*/
8764
class ClosureModule extends Module {
88-
ClosureModule() { getAChildStmt() instanceof GoogModuleDeclaration }
65+
ClosureModule() { any(ClosureModuleDeclaration decl).getTopLevel() = this }
8966

9067
/**
9168
* Gets the call to `goog.module` or `goog.declareModuleId` in this module.
9269
*/
93-
GoogModuleDeclaration getModuleDeclaration() { result = getAChildStmt() }
70+
ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this }
9471

9572
/**
9673
* Gets the namespace of this module.
9774
*/
9875
string getClosureNamespace() { result = getModuleDeclaration().getClosureNamespace() }
9976

10077
override Module getAnImportedModule() {
101-
exists(GoogRequireImport imprt |
102-
imprt.getEnclosingModule() = this and
78+
exists(ClosureRequireCall imprt |
79+
imprt.getTopLevel() = this and
10380
result.(ClosureModule).getClosureNamespace() = imprt.getClosureNamespace()
10481
)
10582
}
@@ -113,7 +90,7 @@ module Closure {
11390
* Has no result for ES6 modules using `goog.declareModuleId`.
11491
*/
11592
Variable getExportsVariable() {
116-
getModuleDeclaration().getFunctionName() = "module" and
93+
getModuleDeclaration().getMethodName() = "module" and
11794
result = getScope().getVariable("exports")
11895
}
11996

@@ -137,26 +114,36 @@ module Closure {
137114
class ClosureScript extends TopLevel {
138115
ClosureScript() {
139116
not this instanceof ClosureModule and
140-
getAChildStmt() instanceof GoogProvide
141-
or
142-
getAChildStmt().(ExprStmt).getExpr() instanceof GoogRequire
117+
(
118+
any(ClosureProvideCall provide).getTopLevel() = this
119+
or
120+
any(ClosureRequireCall require).getTopLevel() = this
121+
)
143122
}
144123

145124
/** Gets the identifier of a namespace required by this module. */
146125
string getARequiredNamespace() {
147-
result = getAChildStmt().(ExprStmt).getExpr().(GoogRequire).getClosureNamespace()
126+
exists(ClosureRequireCall require |
127+
require.getTopLevel() = this and
128+
result = require.getClosureNamespace()
129+
)
148130
}
149131

150132
/** Gets the identifer of a namespace provided by this module. */
151-
string getAProvidedNamespace() { result = getAChildStmt().(GoogProvide).getClosureNamespace() }
133+
string getAProvidedNamespace() {
134+
exists(ClosureProvideCall require |
135+
require.getTopLevel() = this and
136+
result = require.getClosureNamespace()
137+
)
138+
}
152139
}
153140

154141
/**
155142
* Holds if `name` is a closure namespace, including proper namespace prefixes.
156143
*/
157144
pragma[noinline]
158145
predicate isLibraryNamespacePath(string name) {
159-
exists(string namespace | namespace = any(GoogNamespaceRef provide).getClosureNamespace() |
146+
exists(string namespace | namespace = any(ClosureNamespaceRef ref).getClosureNamespace() |
160147
name = namespace.substring(0, namespace.indexOf("."))
161148
or
162149
name = namespace
@@ -185,7 +172,7 @@ module Closure {
185172
result = getWrittenLibraryAccessPath(write)
186173
)
187174
or
188-
result = node.asExpr().(GoogRequire).getClosureNamespace()
175+
result = node.(ClosureRequireCall).getClosureNamespace()
189176
}
190177

191178
/**

0 commit comments

Comments
 (0)