mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #1185 from xiemaisi/js/improve-amd-imports
Approved by asger-semmle
This commit is contained in:
@@ -17,6 +17,6 @@ where
|
||||
not f.inExternsFile() and
|
||||
f.getNumParameter() > 7 and
|
||||
// exclude AMD modules
|
||||
not exists(AMDModuleDefinition m | f = m.getFactoryNode().(DataFlow::FunctionNode).getAstNode())
|
||||
not exists(AmdModuleDefinition m | f = m.getFactoryNode().(DataFlow::FunctionNode).getAstNode())
|
||||
select f.(FirstLineOf),
|
||||
capitalize(f.describe()) + " has too many parameters (" + f.getNumParameter() + ")."
|
||||
|
||||
@@ -23,8 +23,8 @@ import javascript
|
||||
* 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() {
|
||||
class AmdModuleDefinition extends CallExpr {
|
||||
AmdModuleDefinition() {
|
||||
getParent() instanceof ExprStmt and
|
||||
getCallee().(GlobalVarAccess).getName() = "define" and
|
||||
exists(int n | n = getNumArgument() |
|
||||
@@ -153,7 +153,7 @@ class AMDModuleDefinition extends CallExpr {
|
||||
result = getModuleExpr().analyze().getAValue()
|
||||
or
|
||||
// explicit exports: anything assigned to `module.exports`
|
||||
exists(AbstractProperty moduleExports, AMDModule m |
|
||||
exists(AbstractProperty moduleExports, AmdModule m |
|
||||
this = m.getDefine() and
|
||||
moduleExports.getBase().(AbstractModuleObject).getModule() = m and
|
||||
moduleExports.getPropertyName() = "exports"
|
||||
@@ -170,10 +170,15 @@ class AMDModuleDefinition extends CallExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AmdModuleDefinition` instead.
|
||||
*/
|
||||
deprecated class AMDModuleDefinition = AmdModuleDefinition;
|
||||
|
||||
/** An AMD dependency, considered as a path expression. */
|
||||
private class AmdDependencyPath extends PathExprCandidate {
|
||||
AmdDependencyPath() {
|
||||
exists(AMDModuleDefinition amd |
|
||||
exists(AmdModuleDefinition amd |
|
||||
this = amd.getDependencies().getAnElement() or
|
||||
this = amd.getARequireCall().getAnArgument()
|
||||
)
|
||||
@@ -191,21 +196,83 @@ private class ConstantAmdDependencyPathElement extends PathExprInModule, Constan
|
||||
* Holds if `def` is an AMD module definition in `tl` which is not
|
||||
* nested inside another module definition.
|
||||
*/
|
||||
private predicate amdModuleTopLevel(AMDModuleDefinition def, TopLevel tl) {
|
||||
private predicate amdModuleTopLevel(AmdModuleDefinition def, TopLevel tl) {
|
||||
def.getTopLevel() = tl and
|
||||
not def.getParent+() instanceof AMDModuleDefinition
|
||||
not def.getParent+() instanceof AmdModuleDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* An AMD dependency, viewed as an import.
|
||||
*/
|
||||
private class AmdDependencyImport extends Import {
|
||||
AmdDependencyImport() { this = any(AmdModuleDefinition def).getADependency() }
|
||||
|
||||
override Module getEnclosingModule() { this = result.(AmdModule).getDefine().getADependency() }
|
||||
|
||||
override PathExpr getImportedPath() { result = this }
|
||||
|
||||
/**
|
||||
* Gets a file that looks like it might be the target of this import.
|
||||
*
|
||||
* Specifically, we look for files whose absolute path ends with the imported path, possibly
|
||||
* adding well-known JavaScript file extensions like `.js`.
|
||||
*/
|
||||
private File guessTarget() {
|
||||
exists(PathString imported, string abspath, string dirname, string basename |
|
||||
targetCandidate(result, abspath, imported, dirname, basename)
|
||||
|
|
||||
abspath.regexpMatch(".*/\\Q" + imported + "\\E")
|
||||
or
|
||||
exists(Folder dir |
|
||||
// `dir` ends with the dirname of the imported path
|
||||
dir.getAbsolutePath().regexpMatch(".*/\\Q" + dirname + "\\E") or
|
||||
dirname = ""
|
||||
|
|
||||
result = dir.getJavaScriptFile(basename)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is a file whose stem (that is, basename without extension) matches the imported path.
|
||||
*
|
||||
* Additionally, `abspath` is bound to the absolute path of `f`, `imported` to the imported path, and
|
||||
* `dirname` and `basename` to the dirname and basename (respectively) of `imported`.
|
||||
*/
|
||||
private predicate targetCandidate(
|
||||
File f, string abspath, PathString imported, string dirname, string basename
|
||||
) {
|
||||
imported = getImportedPath().getValue() and
|
||||
f.getStem() = imported.getStem() and
|
||||
f.getAbsolutePath() = abspath and
|
||||
dirname = imported.getDirName() and
|
||||
basename = imported.getBaseName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module whose absolute path matches this import, if there is only a single such module.
|
||||
*/
|
||||
private Module resolveByAbsolutePath() {
|
||||
count(guessTarget()) = 1 and
|
||||
result.getFile() = guessTarget()
|
||||
}
|
||||
|
||||
override Module getImportedModule() {
|
||||
result = super.getImportedModule()
|
||||
or
|
||||
not exists(super.getImportedModule()) and
|
||||
result = resolveByAbsolutePath()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An AMD-style module.
|
||||
*/
|
||||
class AMDModule extends Module {
|
||||
AMDModule() { strictcount(AMDModuleDefinition def | amdModuleTopLevel(def, this)) = 1 }
|
||||
class AmdModule extends Module {
|
||||
AmdModule() { strictcount(AmdModuleDefinition def | amdModuleTopLevel(def, this)) = 1 }
|
||||
|
||||
/** Gets the definition of this module. */
|
||||
AMDModuleDefinition getDefine() { amdModuleTopLevel(result, this) }
|
||||
|
||||
override Module getAnImportedModule() { result.getFile() = resolve(getDefine().getADependency()) }
|
||||
AmdModuleDefinition getDefine() { amdModuleTopLevel(result, this) }
|
||||
|
||||
override predicate exports(string name, ASTNode export) {
|
||||
exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() |
|
||||
@@ -214,3 +281,8 @@ class AMDModule extends Module {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AmdModule` instead.
|
||||
*/
|
||||
deprecated class AMDModule = AmdModule;
|
||||
|
||||
@@ -19,8 +19,6 @@ class ES2015Module extends Module {
|
||||
/** Gets an export declaration in this module. */
|
||||
ExportDeclaration getAnExport() { result.getTopLevel() = this }
|
||||
|
||||
override Module getAnImportedModule() { result = getAnImport().getImportedModule() }
|
||||
|
||||
override predicate exports(string name, ASTNode export) {
|
||||
exists(ExportDeclaration ed | ed = getAnExport() and ed = export | ed.exportsAs(_, name))
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ abstract class Container extends @container {
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +101,7 @@ abstract class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) }
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4) }
|
||||
|
||||
/**
|
||||
* Gets the stem of this container, that is, the prefix of its base name up to
|
||||
@@ -120,7 +120,7 @@ abstract class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) }
|
||||
string getStem() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 2) }
|
||||
|
||||
/** Gets the parent container of this file or folder, if any. */
|
||||
Container getParentContainer() { containerparent(result, this) }
|
||||
|
||||
@@ -21,7 +21,7 @@ abstract class Module extends TopLevel {
|
||||
Import getAnImport() { result.getTopLevel() = this }
|
||||
|
||||
/** Gets a module from which this module imports. */
|
||||
abstract Module getAnImportedModule();
|
||||
Module getAnImportedModule() { result = getAnImport().getImportedModule() }
|
||||
|
||||
/** Gets a symbol exported by this module. */
|
||||
string getAnExportedSymbol() { exports(result, _) }
|
||||
@@ -92,8 +92,8 @@ abstract class Module extends TopLevel {
|
||||
}
|
||||
|
||||
/**
|
||||
* An import in a module, which may either be an ECMAScript 2015-style
|
||||
* `import` statement or a CommonJS-style `require` import.
|
||||
* An import in a module, which may be an ECMAScript 2015-style
|
||||
* `import` statement, a CommonJS-style `require` import, or an AMD dependency.
|
||||
*/
|
||||
abstract class Import extends ASTNode {
|
||||
/** Gets the module in which this import appears. */
|
||||
|
||||
@@ -21,9 +21,6 @@ class NodeModule extends Module {
|
||||
/** Gets the scope induced by this module. */
|
||||
override ModuleScope getScope() { result.getScopeElement() = this }
|
||||
|
||||
/** Gets a module imported by this module. */
|
||||
override Module getAnImportedModule() { result = getAnImport().getImportedModule() }
|
||||
|
||||
/**
|
||||
* Gets an abstract value representing one or more values that may flow
|
||||
* into this module's `module.exports` property.
|
||||
|
||||
@@ -76,6 +76,26 @@ private class ConsPath extends Path, TConsPath {
|
||||
override string toString() { result = pp(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a regular expression that can be used to parse slash-separated paths.
|
||||
*
|
||||
* The first capture group captures the dirname of the path, that is, everything
|
||||
* before the last slash, or the empty string if there isn't a slash.
|
||||
*
|
||||
* The second capture group captures the basename of the path, that is, everything
|
||||
* after the last slash, or the entire path if there isn't a slash.
|
||||
*
|
||||
* The third capture group captures the stem of the basename, that is, everything
|
||||
* before the last dot, or the entire basename if there isn't a dot.
|
||||
*
|
||||
* Finally, the fourth and fifth capture groups capture the extension of the basename,
|
||||
* that is, everything after the last dot. The fourth group includes the dot, the
|
||||
* fifth does not.
|
||||
*/
|
||||
private string pathRegex() {
|
||||
result = "(.*)(?:/|^)(([^/]*?)(\\.([^.]*))?)"
|
||||
}
|
||||
|
||||
/**
|
||||
* A string value that represents a (relative or absolute) file system path.
|
||||
*
|
||||
@@ -98,7 +118,17 @@ abstract class PathString extends string {
|
||||
int getNumComponent() { result = count(int i | exists(getComponent(i))) }
|
||||
|
||||
/** Gets the base name of the folder or file this path refers to. */
|
||||
string getBaseName() { result = this.regexpCapture("(.*/|^)([^/]+)", 2) }
|
||||
string getBaseName() { result = this.regexpCapture(pathRegex(), 2) }
|
||||
|
||||
/**
|
||||
* Gets stem of the folder or file this path refers to, that is, the prefix of its base name
|
||||
* up to (but not including) the last dot character if there is one, or the entire
|
||||
* base name if there is not
|
||||
*/
|
||||
string getStem() { result = this.regexpCapture(pathRegex(), 3) }
|
||||
|
||||
/** Gets the path of the parent folder of the folder or file this path refers to. */
|
||||
string getDirName() { result = this.regexpCapture(pathRegex(), 1) }
|
||||
|
||||
/**
|
||||
* Gets the absolute path that the sub-path consisting of the first `n`
|
||||
|
||||
@@ -472,12 +472,12 @@ module ModuleImportNode {
|
||||
)
|
||||
or
|
||||
// declared AMD dependency
|
||||
exists(AMDModuleDefinition amd |
|
||||
exists(AmdModuleDefinition amd |
|
||||
this = DataFlow::parameterNode(amd.getDependencyParameter(path))
|
||||
)
|
||||
or
|
||||
// AMD require
|
||||
exists(AMDModuleDefinition amd, CallExpr req |
|
||||
exists(AmdModuleDefinition amd, CallExpr req |
|
||||
req = amd.getARequireCall() and
|
||||
this = DataFlow::valueNode(req) and
|
||||
path = req.getArgument(0).(ConstantString).getStringValue()
|
||||
|
||||
@@ -61,7 +61,7 @@ private predicate mayDynamicallyComputeExports(Module m) {
|
||||
or
|
||||
// AMD modules can export arbitrary objects, so an import is essentially a property read
|
||||
// and hence must be considered indefinite
|
||||
m instanceof AMDModule
|
||||
m instanceof AmdModule
|
||||
or
|
||||
// `m` re-exports all exports of some other module that dynamically computes its exports
|
||||
exists(BulkReExportDeclaration rexp | rexp = m.(ES2015Module).getAnExport() |
|
||||
@@ -229,7 +229,7 @@ class AnalyzedExternalModuleReference extends AnalyzedPropertyRead, DataFlow::Va
|
||||
* Flow analysis for AMD exports.
|
||||
*/
|
||||
private class AnalyzedAmdExport extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
AMDModule amd;
|
||||
AmdModule amd;
|
||||
|
||||
AnalyzedAmdExport() { astNode = amd.getDefine().getModuleExpr() }
|
||||
|
||||
@@ -248,7 +248,7 @@ private class AnalyzedAmdImport extends AnalyzedPropertyRead, DataFlow::Node {
|
||||
Module required;
|
||||
|
||||
AnalyzedAmdImport() {
|
||||
exists(AMDModule amd, PathExpr dep, Parameter p |
|
||||
exists(AmdModule amd, PathExpr dep, Parameter p |
|
||||
amd.getDefine().dependencyParameter(dep, p) and
|
||||
this = DataFlow::parameterNode(p) and
|
||||
required.getFile() = amd.resolve(dep)
|
||||
|
||||
@@ -180,7 +180,7 @@ private class AnalyzedAmdParameter extends AnalyzedVarDef {
|
||||
AbstractValue implicitInitVal;
|
||||
|
||||
AnalyzedAmdParameter() {
|
||||
exists(AMDModule m, AMDModuleDefinition mdef | mdef = m.getDefine() |
|
||||
exists(AmdModule m, AmdModuleDefinition mdef | mdef = m.getDefine() |
|
||||
this = mdef.getModuleParameter() and
|
||||
implicitInitVal = TAbstractModuleObject(m)
|
||||
or
|
||||
|
||||
@@ -57,7 +57,7 @@ module TaintedPath {
|
||||
ModulePathSink() {
|
||||
astNode = any(Require rq).getArgument(0) or
|
||||
astNode = any(ExternalModuleReference rq).getExpression() or
|
||||
astNode = any(AMDModuleDefinition amd).getDependencies()
|
||||
astNode = any(AmdModuleDefinition amd).getDependencies()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
| a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:2:12:2:22 | { foo: 42 } | a.js:2:12:2:22 | { foo: 42 } |
|
||||
| dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} | dir/b.js:1:8:3:1 | {\\n bar: 42\\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 } |
|
||||
| umd.js:4:9:4:43 | define( ... actory) | umd.js:10:12:13:5 | {\\n ... r\\n } | umd.js:10:12:13:5 | {\\n ... r\\n } |
|
||||
@@ -1,5 +0,0 @@
|
||||
| tst3.js:1:1:3:3 | <toplevel> | a.js:1:1:3:3 | <toplevel> |
|
||||
| tst.js:1:1:6:3 | <toplevel> | a.js:1:1:3:3 | <toplevel> |
|
||||
| tst.js:1:1:6:3 | <toplevel> | dir/b.js:1:1:3:3 | <toplevel> |
|
||||
| umd.js:1:1:14:4 | <toplevel> | a.js:1:1:3:3 | <toplevel> |
|
||||
| umd.js:1:1:14:4 | <toplevel> | dir/b.js:1:1:3:3 | <toplevel> |
|
||||
@@ -1,4 +0,0 @@
|
||||
import javascript
|
||||
|
||||
from AMDModule m
|
||||
select m, m.getAnImportedModule()
|
||||
@@ -1,6 +1,10 @@
|
||||
| a.js:1:1:3:3 | <toplevel> | a.js:1:1:3:2 | define( ... 2 };\\n}) |
|
||||
| dir/b.js:1:1:3:3 | <toplevel> | dir/b.js:1:1:3:2 | define( ... : 42\\n}) |
|
||||
| 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}) |
|
||||
| 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}) |
|
||||
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:1:6:2 | define( ... };\\n}) |
|
||||
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:9:4:43 | define( ... actory) |
|
||||
@@ -1,4 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from AMDModule m
|
||||
from AmdModule m
|
||||
select m, m.getDefine()
|
||||
@@ -1,6 +1,10 @@
|
||||
| a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:1:8:3:1 | functio ... 42 };\\n} |
|
||||
| dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} |
|
||||
| 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} |
|
||||
| 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} |
|
||||
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:28:6:1 | functio ... };\\n} |
|
||||
| umd.js:4:9:4:43 | define( ... actory) | umd.js:9:9:14:1 | functio ... };\\n} |
|
||||
@@ -1,4 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from AMDModuleDefinition d
|
||||
from AmdModuleDefinition d
|
||||
select d, d.getFactoryNode()
|
||||
@@ -1,5 +1,9 @@
|
||||
| tst2.js:1:1:3:2 | define( ... 42;\\n}) | tst2.js:1:9:1:17 | 'exports' |
|
||||
| tst3.js:1:1:3:2 | define( ... 42;\\n}) | tst3.js:2:21:2:25 | './a' |
|
||||
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:2:9:2:14 | 'a.js' |
|
||||
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:3:9:3:13 | 'foo' |
|
||||
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:4:9:4:18 | 'nested/a' |
|
||||
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:5:9:5:20 | 'lib/foo.js' |
|
||||
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:9:1:13 | './a' |
|
||||
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:16:1:24 | './dir/b' |
|
||||
| umd.js:4:9:4:43 | define( ... actory) | umd.js:4:17:4:21 | './a' |
|
||||
@@ -1,4 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from AMDModuleDefinition d
|
||||
from AmdModuleDefinition d
|
||||
select d, d.getADependency()
|
||||
@@ -1,7 +1,12 @@
|
||||
| a.js:1:1:3:3 | <toplevel> | foo |
|
||||
| dir/b.js:1:1:3:3 | <toplevel> | bar |
|
||||
| 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 |
|
||||
| tst2.js:1:1:3:3 | <toplevel> | foo |
|
||||
| tst3.js:1:1:3:3 | <toplevel> | foo |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | bar |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | foo |
|
||||
| tst.js:1:1:6:3 | <toplevel> | bar |
|
||||
| tst.js:1:1:6:3 | <toplevel> | foo |
|
||||
| umd.js:1:1:14:4 | <toplevel> | bar |
|
||||
@@ -1,4 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from AMDModule m
|
||||
from AmdModule m
|
||||
select m, m.getAnExportedSymbol()
|
||||
@@ -0,0 +1,8 @@
|
||||
| a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:2:12:2:22 | { foo: 42 } | a.js:2:12:2:22 | { foo: 42 } |
|
||||
| dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} |
|
||||
| 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 } |
|
||||
| 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 } |
|
||||
| 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 } |
|
||||
| umd.js:4:9:4:43 | define( ... actory) | umd.js:10:12:13:5 | {\\n ... r\\n } | umd.js:10:12:13:5 | {\\n ... r\\n } |
|
||||
@@ -1,4 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from AMDModuleDefinition d
|
||||
from AmdModuleDefinition d
|
||||
select d, d.getModuleExpr(), d.getAModuleSource()
|
||||
@@ -0,0 +1,8 @@
|
||||
| tst3.js:1:1:3:3 | <toplevel> | tst3.js:2:21:2:25 | './a' | a.js:1:1:3:3 | <toplevel> |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | tst4.js:3:9:3:13 | 'foo' | lib/foo.js:1:1:4:0 | <toplevel> |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | tst4.js:4:9:4:18 | 'nested/a' | lib/nested/a.js:1:1:3:3 | <toplevel> |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | tst4.js:5:9:5:20 | 'lib/foo.js' | lib/foo.js:1:1:4:0 | <toplevel> |
|
||||
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:9:1:13 | './a' | a.js:1:1:3:3 | <toplevel> |
|
||||
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:16:1:24 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
|
||||
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:17:4:21 | './a' | a.js:1:1:3:3 | <toplevel> |
|
||||
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:24:4:32 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from AmdModule m, Import i
|
||||
where i = m.getAnImport()
|
||||
select m, i, i.getImportedModule()
|
||||
@@ -1,7 +1,12 @@
|
||||
| a.js:1:1:3:3 | <toplevel> | foo | a.js:2:14:2:20 | foo: 42 |
|
||||
| dir/b.js:1:1:3:3 | <toplevel> | bar | dir/b.js:2:5:2:11 | bar: 42 |
|
||||
| lib/a.js:1:1:3:3 | <toplevel> | foo | lib/a.js:2:14:2:20 | foo: 42 |
|
||||
| lib/foo.js:1:1:4:0 | <toplevel> | foo | lib/foo.js:2:5:2:11 | foo: 23 |
|
||||
| lib/nested/a.js:1:1:3:3 | <toplevel> | foo | lib/nested/a.js:2:14:2:20 | foo: 42 |
|
||||
| tst2.js:1:1:3:3 | <toplevel> | foo | tst2.js:2:5:2:15 | exports.foo |
|
||||
| tst3.js:1:1:3:3 | <toplevel> | foo | tst3.js:2:29:2:39 | exports.foo |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | bar | tst4.js:9:9:9:18 | bar: b.bar |
|
||||
| tst4.js:1:1:11:3 | <toplevel> | foo | tst4.js:8:9:8:18 | foo: a.foo |
|
||||
| tst.js:1:1:6:3 | <toplevel> | bar | tst.js:4:9:4:18 | bar: b.bar |
|
||||
| tst.js:1:1:6:3 | <toplevel> | foo | tst.js:3:9:3:18 | foo: a.foo |
|
||||
| umd.js:1:1:14:4 | <toplevel> | bar | umd.js:11:9:11:18 | bar: a.foo |
|
||||
3
javascript/ql/test/library-tests/AMD/lib/a.js
Normal file
3
javascript/ql/test/library-tests/AMD/lib/a.js
Normal file
@@ -0,0 +1,3 @@
|
||||
define(function() {
|
||||
return { foo: 42 };
|
||||
});
|
||||
3
javascript/ql/test/library-tests/AMD/lib/foo.js
Normal file
3
javascript/ql/test/library-tests/AMD/lib/foo.js
Normal file
@@ -0,0 +1,3 @@
|
||||
define({
|
||||
foo: 23
|
||||
});
|
||||
3
javascript/ql/test/library-tests/AMD/lib/nested/a.js
Normal file
3
javascript/ql/test/library-tests/AMD/lib/nested/a.js
Normal file
@@ -0,0 +1,3 @@
|
||||
define(function() {
|
||||
return { foo: 42 };
|
||||
});
|
||||
11
javascript/ql/test/library-tests/AMD/tst4.js
Normal file
11
javascript/ql/test/library-tests/AMD/tst4.js
Normal file
@@ -0,0 +1,11 @@
|
||||
define([
|
||||
'a.js', // not resolved: ambiguous
|
||||
'foo', // resolved to `lib/foo.js`
|
||||
'nested/a', // resolved to `lib/nested/a.js`
|
||||
'lib/foo.js' // resolved to `lib/foo.js`
|
||||
], function(a, b, exports) {
|
||||
return {
|
||||
foo: a.foo,
|
||||
bar: b.bar
|
||||
};
|
||||
});
|
||||
@@ -10,7 +10,7 @@ string getModuleType(TopLevel top) {
|
||||
top instanceof ES2015Module and
|
||||
result = "es2015"
|
||||
or
|
||||
top instanceof AMDModule and
|
||||
top instanceof AmdModule and
|
||||
result = "amd"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user