Skip to content

Commit c07cc6e

Browse files
committed
Repair Closure implementation
1 parent e3e2749 commit c07cc6e

File tree

2 files changed

+39
-68
lines changed

2 files changed

+39
-68
lines changed

javascript/ql/lib/semmle/javascript/Closure.qll

+31-19
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@
55
import javascript
66

77
module Closure {
8+
/** A call to `goog.require` */
9+
class RequireCallExpr extends CallExpr {
10+
RequireCallExpr() { this.getCallee().(PropAccess).getQualifiedName() = "goog.require" }
11+
12+
/** Gets the imported namespace name. */
13+
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
14+
}
15+
16+
/** A call to `goog.module` or `goog.declareModuleId`. */
17+
private class ModuleDeclarationCall extends CallExpr {
18+
private string kind;
19+
20+
ModuleDeclarationCall() {
21+
this.getCallee().(PropAccess).getQualifiedName() = kind and
22+
kind = ["goog.module", "goog.declareModuleId"]
23+
}
24+
25+
/** Gets the declared namespace. */
26+
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
27+
28+
/** Gets the string `goog.module` or `goog.declareModuleId` depending on which method is being called. */
29+
string getModuleKind() { result = kind }
30+
}
31+
832
/**
933
* A reference to a Closure namespace.
1034
*/
@@ -109,38 +133,26 @@ module Closure {
109133
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration
110134
{ }
111135

112-
private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) }
113-
114-
pragma[nomagic]
115-
private MethodCallExpr googModuleDeclExpr() {
116-
result.getReceiver() = googVariable().getAnAccess() and
117-
result.getMethodName() = ["module", "declareModuleId"]
118-
}
119-
120-
pragma[nomagic]
121-
private MethodCallExpr googModuleDeclExprInContainer(StmtContainer container) {
122-
result = googModuleDeclExpr() and
123-
container = result.getContainer()
124-
}
125-
126136
pragma[noinline]
127-
private ClosureRequireCall getARequireInTopLevel(ClosureModule m) { result.getTopLevel() = m }
137+
private RequireCallExpr getARequireInTopLevel(ClosureModule m) { result.getTopLevel() = m }
128138

129139
/**
130140
* A module using the Closure module system, declared using `goog.module()` or `goog.declareModuleId()`.
131141
*/
132142
class ClosureModule extends Module {
133-
ClosureModule() { exists(googModuleDeclExprInContainer(this)) }
143+
private ModuleDeclarationCall decl;
144+
145+
ClosureModule() { decl.getTopLevel() = this }
134146

135147
/**
136148
* Gets the call to `goog.module` or `goog.declareModuleId` in this module.
137149
*/
138-
ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this }
150+
deprecated ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this }
139151

140152
/**
141153
* Gets the namespace of this module.
142154
*/
143-
string getClosureNamespace() { result = this.getModuleDeclaration().getClosureNamespace() }
155+
string getClosureNamespace() { result = decl.getClosureNamespace() }
144156

145157
override Module getAnImportedModule() {
146158
result.(ClosureModule).getClosureNamespace() =
@@ -156,7 +168,7 @@ module Closure {
156168
* Has no result for ES6 modules using `goog.declareModuleId`.
157169
*/
158170
Variable getExportsVariable() {
159-
this.getModuleDeclaration().getMethodName() = "module" and
171+
decl.getModuleKind() = "goog.module" and
160172
result = this.getScope().getVariable("exports")
161173
}
162174

javascript/ql/lib/semmle/javascript/internal/NameResolution.qll

+8-49
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,13 @@ module NameResolution {
138138
node2 = type
139139
)
140140
or
141-
exists(ClosureModuleDeclaration decl, ClosureImport imprt |
142-
decl.getClosureNamespace() = imprt.getClosureNamespace() and
143-
node1 = decl.getContainer() and
144-
node2 = imprt
141+
exists(Closure::RequireCallExpr req |
142+
node1.(Closure::ClosureModule).getClosureNamespace() = req.getClosureNamespace() and
143+
node2 = req
145144
)
146145
or
147146
exists(Closure::ClosureModule mod |
148-
node1 = mod.getScope().getVariable("exports") and
147+
node1 = mod.getExportsVariable() and
149148
node2 = mod
150149
)
151150
or
@@ -155,45 +154,6 @@ module NameResolution {
155154
)
156155
}
157156

158-
class ClosureImport extends CallExpr {
159-
ClosureImport() { this.getCallee().(PropAccess).getQualifiedName() = "goog.require" }
160-
161-
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
162-
}
163-
164-
class ClosureModuleDeclaration extends CallExpr {
165-
private string kind;
166-
167-
ClosureModuleDeclaration() {
168-
this.getCallee().(PropAccess).getQualifiedName() = kind and
169-
kind = ["goog.module", "goog.declareModuleId"]
170-
}
171-
172-
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
173-
174-
string getModuleKind() { result = kind }
175-
}
176-
177-
class ClosureExport extends AssignExpr {
178-
private PropAccess lhs;
179-
180-
ClosureExport() {
181-
exists(ClosureModuleDeclaration decl, Module mod |
182-
decl.getModuleKind() = "goog.module" and
183-
decl.getContainer() = mod and
184-
this.getTopLevel() = mod and
185-
this.getLhs() = lhs and
186-
lhs.getBase() = mod.getScope().getVariable("exports").getAnAccess()
187-
)
188-
}
189-
190-
string getName() { result = lhs.getPropertyName() }
191-
192-
Module getModule() { result = this.getTopLevel() }
193-
194-
Expr getValue() { result = this.getRhs() }
195-
}
196-
197157
/**
198158
* Holds if there is a read from `node1` to `node2` that accesses the member `name`.
199159
*/
@@ -320,10 +280,9 @@ module NameResolution {
320280
result = enum.getMemberByName(name).getIdentifier()
321281
)
322282
or
323-
exists(ClosureExport exprt |
324-
mod = exprt.getModule() and
325-
name = exprt.getName() and
326-
result = exprt.getValue()
283+
exists(AssignExpr assign, PropAccess lhs |
284+
lhs.accesses(mod.(Closure::ClosureModule).getExportsVariable().getAnAccess(), name) and
285+
result = assign.getRhs()
327286
)
328287
}
329288

@@ -465,7 +424,7 @@ module NameResolution {
465424
)
466425
or
467426
mod = "global" and
468-
qualifiedName = node.(ClosureImport).getClosureNamespace()
427+
qualifiedName = node.(Closure::RequireCallExpr).getClosureNamespace()
469428
or
470429
// Additionally track through bulk re-exports (`export * from 'mod`).
471430
// These are normally handled by 'exportAs' which supports various shadowing rules,

0 commit comments

Comments
 (0)