Skip to content

Commit 613895e

Browse files
authored
Merge pull request #20424 from asgerf/js/overlay-manual-v4
JS: Add overlay annotations
2 parents 0c43f2c + efa438a commit 613895e

File tree

110 files changed

+780
-62
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+780
-62
lines changed

javascript/ql/lib/Expressions/ExprHasNoEffect.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes and predicates for the 'js/useless-expression' query.
33
*/
4+
overlay[local]
5+
module;
46

57
import javascript
68
import DOMProperties
@@ -60,6 +62,7 @@ predicate isDeclaration(Expr e) {
6062
/**
6163
* Holds if there exists a getter for a property called `name` anywhere in the program.
6264
*/
65+
overlay[global]
6366
predicate isGetterProperty(string name) {
6467
// there is a call of the form `Object.defineProperty(..., name, descriptor)` ...
6568
exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() |
@@ -85,6 +88,7 @@ predicate isGetterProperty(string name) {
8588
/**
8689
* A property access that may invoke a getter.
8790
*/
91+
overlay[global]
8892
class GetterPropertyAccess extends PropAccess {
8993
override predicate isImpure() { isGetterProperty(this.getPropertyName()) }
9094
}
@@ -123,6 +127,7 @@ predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) {
123127
* even if they do, the call itself is useless and should be flagged by this
124128
* query.
125129
*/
130+
overlay[global]
126131
predicate noSideEffects(Expr e) {
127132
e.isPure()
128133
or
@@ -148,6 +153,7 @@ predicate isCompoundExpression(Expr e) {
148153
/**
149154
* Holds if the expression `e` should be reported as having no effect.
150155
*/
156+
overlay[global]
151157
predicate hasNoEffect(Expr e) {
152158
noSideEffects(e) and
153159
inVoidContext(e) and

javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides a predicate for identifying unused index variables in loops.
33
*/
4+
overlay[local]
5+
module;
46

57
import javascript
68

javascript/ql/lib/semmle/javascript/AMD.qll

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Provides classes for working with
33
* [Asynchronous Module Definitions](https://github.com/amdjs/amdjs-api/wiki/AMD).
44
*/
5+
overlay[local]
6+
module;
57

68
import javascript
79
private import semmle.javascript.internal.CachedStages
@@ -62,9 +64,11 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range
6264
}
6365

6466
/** DEPRECATED. Use `getDependencyExpr` instead. */
67+
overlay[global]
6568
deprecated PathExpr getDependency(int i) { result = this.getDependencyExpr(i) }
6669

6770
/** DEPRECATED. Use `getADependencyExpr` instead. */
71+
overlay[global]
6872
deprecated PathExpr getADependency() { result = this.getADependencyExpr() }
6973

7074
/** Gets the `i`th dependency of this module definition. */
@@ -194,16 +198,19 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range
194198
* Gets an abstract value representing one or more values that may flow
195199
* into this module's `module.exports` property.
196200
*/
201+
overlay[global]
197202
DefiniteAbstractValue getAModuleExportsValue() {
198203
result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()]
199204
}
200205

206+
overlay[global]
201207
pragma[noinline, nomagic]
202208
private AbstractValue getAnImplicitExportsValue() {
203209
// implicit exports: anything that is returned from the factory function
204210
result = this.getModuleExpr().analyze().getAValue()
205211
}
206212

213+
overlay[global]
207214
pragma[noinline]
208215
private AbstractValue getAnExplicitExportsValue() {
209216
// explicit exports: anything assigned to `module.exports`
@@ -227,6 +234,7 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range
227234
private predicate isPseudoDependency(string s) { s = ["exports", "require", "module"] }
228235

229236
/** An AMD dependency, considered as a path expression. */
237+
overlay[global]
230238
private class AmdDependencyPath extends PathExprCandidate {
231239
AmdDependencyPath() {
232240
exists(AmdModuleDefinition amd |
@@ -239,6 +247,7 @@ private class AmdDependencyPath extends PathExprCandidate {
239247
}
240248

241249
/** A constant path element appearing in an AMD dependency expression. */
250+
overlay[global]
242251
deprecated private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString {
243252
ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() }
244253

@@ -281,6 +290,7 @@ private class AmdDependencyImport extends Import {
281290
* Specifically, we look for files whose absolute path ends with the imported path, possibly
282291
* adding well-known JavaScript file extensions like `.js`.
283292
*/
293+
overlay[global]
284294
private File guessTarget() {
285295
exists(FilePath imported, string abspath, string dirname, string basename |
286296
this.targetCandidate(result, abspath, imported, dirname, basename)
@@ -303,6 +313,7 @@ private class AmdDependencyImport extends Import {
303313
* Additionally, `abspath` is bound to the absolute path of `f`, `imported` to the imported path, and
304314
* `dirname` and `basename` to the dirname and basename (respectively) of `imported`.
305315
*/
316+
overlay[global]
306317
private predicate targetCandidate(
307318
File f, string abspath, FilePath imported, string dirname, string basename
308319
) {
@@ -316,10 +327,12 @@ private class AmdDependencyImport extends Import {
316327
/**
317328
* Gets the module whose absolute path matches this import, if there is only a single such module.
318329
*/
330+
overlay[global]
319331
private Module resolveByAbsolutePath() {
320332
result.getFile() = unique(File file | file = this.guessTarget())
321333
}
322334

335+
overlay[global]
323336
override Module getImportedModule() {
324337
result = super.getImportedModule()
325338
or
@@ -348,21 +361,20 @@ private class AmdDependencyImport extends Import {
348361
*/
349362
class AmdModule extends Module {
350363
cached
351-
AmdModule() {
352-
Stages::DataFlowStage::ref() and
353-
exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this)))
354-
}
364+
AmdModule() { exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this))) }
355365

356366
/** Gets the definition of this module. */
357367
AmdModuleDefinition getDefine() { amdModuleTopLevel(result, this) }
358368

369+
overlay[global]
359370
override DataFlow::Node getAnExportedValue(string name) {
360371
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
361372
pwn.getBase().analyze().getAValue() = this.getDefine().getAModuleExportsValue() and
362373
name = pwn.getPropertyName()
363374
)
364375
}
365376

377+
overlay[global]
366378
override DataFlow::Node getABulkExportedNode() {
367379
// Assigned to `module.exports` via the factory's `module` parameter
368380
exists(AbstractModuleObject m, DataFlow::PropWrite write |

javascript/ql/lib/semmle/javascript/AST.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes for working with the AST-based representation of JavaScript programs.
33
*/
4+
overlay[local]
5+
module;
46

57
import javascript
68
private import internal.StmtContainers
@@ -172,6 +174,7 @@ class AstNode extends @ast_node, NodeInStmtContainer {
172174
* The TypeScript compiler emits no code for ambient declarations, but they
173175
* can affect name resolution and type checking at compile-time.
174176
*/
177+
overlay[caller?]
175178
pragma[inline]
176179
predicate isAmbient() {
177180
this.isAmbientInternal()
@@ -470,9 +473,12 @@ module AST {
470473
*/
471474
class ValueNode extends AstNode, @dataflownode {
472475
/** Gets type inference results for this element. */
476+
overlay[global]
473477
DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() }
474478

475479
/** Gets the data flow node associated with this program element. */
480+
overlay[caller]
481+
pragma[inline]
476482
DataFlow::ValueNode flow() { result = DataFlow::valueNode(this) }
477483

478484
/**
@@ -481,6 +487,7 @@ module AST {
481487
* This can be used to map an expression to the class it refers to, or
482488
* associate it with a named value coming from an dependency.
483489
*/
490+
overlay[global]
484491
ExprNameBindingNode getNameBinding() { result = this }
485492

486493
/**
@@ -490,6 +497,7 @@ module AST {
490497
* (according to the type system), or to associate it with a named type coming
491498
* from a dependency.
492499
*/
500+
overlay[global]
493501
TypeNameBindingNode getTypeBinding() { TypeResolution::valueHasType(this, result) }
494502
}
495503
}

javascript/ql/lib/semmle/javascript/CFG.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@
272272
* Note that the `import` statement as a whole is part of the CFG of the body, while its single
273273
* import specifier `x as y` forms part of the preamble.
274274
*/
275+
overlay[local]
276+
module;
275277

276278
import javascript
277279
private import internal.StmtContainers

javascript/ql/lib/semmle/javascript/Classes.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* Class declarations and class expressions are modeled by (QL) classes `ClassDeclaration`
55
* and `ClassExpression`, respectively, which are both subclasses of `ClassDefinition`.
66
*/
7+
overlay[local]
8+
module;
79

810
import javascript
911

@@ -119,6 +121,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
119121
*
120122
* Anonymous classes and interfaces do not have a canonical name.
121123
*/
124+
overlay[global]
122125
deprecated TypeName getTypeName() { result.getADefinition() = this }
123126

124127
/**
@@ -253,6 +256,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
253256
/**
254257
* Gets the definition of the super class of this class, if it can be determined.
255258
*/
259+
overlay[global]
256260
ClassDefinition getSuperClassDefinition() {
257261
result = this.getSuperClass().analyze().getAValue().(AbstractClass).getClass()
258262
}
@@ -580,6 +584,7 @@ class MemberDeclaration extends @property, Documentable {
580584
int getMemberIndex() { properties(this, _, result, _, _) }
581585

582586
/** Holds if the name of this member is computed by an impure expression. */
587+
overlay[global]
583588
predicate hasImpureNameExpr() { this.isComputed() and this.getNameExpr().isImpure() }
584589

585590
/**

0 commit comments

Comments
 (0)