mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #817 from asger-semmle/closure-modules
Approved by esben-semmle, xiemaisi
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
|
||||
* Type inference for function calls has been improved. This may give additional results for queries that rely on type inference.
|
||||
|
||||
* The [Closure-Library](https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide) module system is now supported.
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|
||||
@@ -306,7 +306,7 @@ public class ASTExtractor {
|
||||
public V(Platform platform, SourceType sourceType) {
|
||||
this.platform = platform;
|
||||
this.sourceType = sourceType;
|
||||
this.isStrict = sourceType == SourceType.MODULE;
|
||||
this.isStrict = sourceType.isStrictMode();
|
||||
}
|
||||
|
||||
private Label visit(INode child, Label parent, int childIndex) {
|
||||
@@ -546,31 +546,37 @@ public class ASTExtractor {
|
||||
|
||||
isStrict = hasUseStrict(nd.getBody());
|
||||
|
||||
// if we're extracting a Node.js/ES2015 module, introduce module scope
|
||||
if (platform == Platform.NODE) {
|
||||
// add node.js-specific globals
|
||||
scopeManager.addVariables("global", "process", "console", "Buffer");
|
||||
// Add platform-specific globals.
|
||||
scopeManager.addVariables(platform.getPredefinedGlobals());
|
||||
|
||||
// Introduce local scope if there is one.
|
||||
if (sourceType.hasLocalScope()) {
|
||||
Label moduleScopeKey = trapwriter.globalID("module;{" + locationManager.getFileLabel() + "}," + locationManager.getStartLine() + "," + locationManager.getStartColumn());
|
||||
scopeManager.enterScope(3, moduleScopeKey, toplevelLabel);
|
||||
// special variables aren't available in `.mjs` modules
|
||||
if (!".mjs".equals(locationManager.getSourceFileExtension()))
|
||||
scopeManager.addVariables("require", "module", "exports", "__filename", "__dirname", "arguments");
|
||||
trapwriter.addTuple("isModule", toplevelLabel);
|
||||
} else if (sourceType == SourceType.MODULE) {
|
||||
Label moduleScopeKey = trapwriter.globalID("module;{" + locationManager.getFileLabel() + "}," + locationManager.getStartLine() + "," + locationManager.getStartColumn());
|
||||
scopeManager.enterScope(3, moduleScopeKey, toplevelLabel);
|
||||
scopeManager.addVariables(sourceType.getPredefinedLocals(platform, locationManager.getSourceFileExtension()));
|
||||
trapwriter.addTuple("isModule", toplevelLabel);
|
||||
}
|
||||
|
||||
// Emit the specific source type.
|
||||
switch (sourceType) {
|
||||
case CLOSURE_MODULE:
|
||||
trapwriter.addTuple("isClosureModule", toplevelLabel);
|
||||
break;
|
||||
case MODULE:
|
||||
trapwriter.addTuple("isES2015Module", toplevelLabel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// add all declared global (or module-scoped) names, both non-lexical and lexical
|
||||
scopeManager.addNames(scopeManager.collectDeclaredNames(nd, isStrict, false, DeclKind.none));
|
||||
scopeManager.addNames(scopeManager.collectDeclaredNames(nd, isStrict, true, DeclKind.none));
|
||||
|
||||
visitAll(nd.getBody(), toplevelLabel);
|
||||
|
||||
// if we're extracting a Node.js/ES2015 module, leave its scope
|
||||
if (platform == Platform.NODE || sourceType == SourceType.MODULE)
|
||||
// Leave the local scope again.
|
||||
if (sourceType.hasLocalScope())
|
||||
scopeManager.leaveScope();
|
||||
|
||||
contextManager.leaveContainer();
|
||||
|
||||
@@ -4,7 +4,12 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.semmle.js.parser.JcornWrapper;
|
||||
import com.semmle.util.data.StringUtil;
|
||||
import com.semmle.util.exception.UserError;
|
||||
|
||||
@@ -50,13 +55,75 @@ public class ExtractorConfig {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of a source file, which together with the {@link Platform}
|
||||
* determines how the top-level scope of the file behaves, and whether ES2015
|
||||
* module syntax should be allowed.
|
||||
* <p>
|
||||
* Note that the names of these enum members are depended on by {@link Main},
|
||||
* {@link AutoBuild}, and {@link JcornWrapper}.
|
||||
*/
|
||||
public static enum SourceType {
|
||||
SCRIPT, MODULE, AUTO;
|
||||
/** A script executed in the global scope. */
|
||||
SCRIPT,
|
||||
|
||||
/** An ES2015 module. */
|
||||
MODULE,
|
||||
|
||||
/** A Closure-Library module, defined using `goog.module()`. */
|
||||
CLOSURE_MODULE,
|
||||
|
||||
/** A CommonJS module that is not also an ES2015 module. */
|
||||
COMMONJS_MODULE,
|
||||
|
||||
/** Automatically determined source type. */
|
||||
AUTO;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringUtil.lc(name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this source is executed directly in the global scope,
|
||||
* or false if it has its own local scope.
|
||||
*/
|
||||
public boolean hasLocalScope() {
|
||||
return this != SCRIPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this source is implicitly in strict mode.
|
||||
*/
|
||||
public boolean isStrictMode() {
|
||||
return this == MODULE;
|
||||
}
|
||||
|
||||
private static final Set<String> closureLocals = Collections.singleton("exports");
|
||||
private static final Set<String> commonJsLocals = new LinkedHashSet<>(Arrays.asList("require", "module", "exports", "__filename", "__dirname", "arguments"));
|
||||
|
||||
/**
|
||||
* Returns the set of local variables in scope at the top-level of this module.
|
||||
* <p/>
|
||||
* If this source type has no local scope, the empty set is returned.
|
||||
*/
|
||||
public Set<String> getPredefinedLocals(Platform platform, String extension) {
|
||||
switch (this) {
|
||||
case CLOSURE_MODULE:
|
||||
return closureLocals;
|
||||
case COMMONJS_MODULE:
|
||||
return commonJsLocals;
|
||||
case MODULE:
|
||||
if (platform == Platform.NODE && !extension.equals(".mjs")) {
|
||||
// An ES2015 module that is compiled to a Node.js module effectively has the locals
|
||||
// from Node.js even if they are not part of the ES2015 standard.
|
||||
return commonJsLocals;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
default:
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static enum Platform {
|
||||
@@ -66,6 +133,15 @@ public class ExtractorConfig {
|
||||
public String toString() {
|
||||
return StringUtil.lc(name());
|
||||
}
|
||||
|
||||
private static final Set<String> nodejsGlobals = new LinkedHashSet<>(Arrays.asList("global", "process", "console", "Buffer"));
|
||||
|
||||
/**
|
||||
* Gets the set of predefined globals for this platform.
|
||||
*/
|
||||
public Set<String> getPredefinedGlobals() {
|
||||
return this == NODE ? nodejsGlobals : Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,8 +29,8 @@ public class JSExtractor {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
// heuristic: if `import` or `export` appears at the beginning of a line, it's probably a module
|
||||
private static final Pattern containsImportOrExport = Pattern.compile("(?m)^([ \t]*)(import|export)\\b");
|
||||
// heuristic: if `import`, `export`, or `goog.module` appears at the beginning of a line, it's probably a module
|
||||
private static final Pattern containsModuleIndicator = Pattern.compile("(?m)^([ \t]*)(import|export|goog\\.module)\\b");
|
||||
|
||||
public Pair<Label, LoCInfo> extract(TextualExtractor textualExtractor, String source, int toplevelKind, ScopeManager scopeManager) throws ParseError {
|
||||
// if the file starts with `{ "<string>":` it won't parse as JavaScript; try parsing as JSON instead
|
||||
@@ -69,9 +69,10 @@ public class JSExtractor {
|
||||
if (sourceType != SourceType.AUTO)
|
||||
return sourceType;
|
||||
if (config.getEcmaVersion().compareTo(ECMAVersion.ECMA2015) >= 0) {
|
||||
Matcher m = containsImportOrExport.matcher(source);
|
||||
if (m.find() && (allowLeadingWS || m.group(1).isEmpty()))
|
||||
return SourceType.MODULE;
|
||||
Matcher m = containsModuleIndicator.matcher(source);
|
||||
if (m.find() && (allowLeadingWS || m.group(1).isEmpty())) {
|
||||
return m.group(2).startsWith("goog") ? SourceType.CLOSURE_MODULE : SourceType.MODULE;
|
||||
}
|
||||
}
|
||||
return SourceType.SCRIPT;
|
||||
}
|
||||
@@ -89,6 +90,9 @@ public class JSExtractor {
|
||||
LoCInfo loc;
|
||||
if (ast != null) {
|
||||
platform = getPlatform(platform, ast);
|
||||
if (sourceType == SourceType.SCRIPT && platform == Platform.NODE) {
|
||||
sourceType = SourceType.COMMONJS_MODULE;
|
||||
}
|
||||
|
||||
lexicalExtractor = new LexicalExtractor(textualExtractor, parserRes.getTokens(), parserRes.getComments());
|
||||
ASTExtractor scriptExtractor = new ASTExtractor(lexicalExtractor, scopeManager);
|
||||
@@ -125,7 +129,7 @@ public class JSExtractor {
|
||||
|
||||
if (config.isExterns())
|
||||
textualExtractor.getTrapwriter().addTuple("isExterns", toplevelLabel);
|
||||
if (platform == Platform.NODE && sourceType != SourceType.MODULE)
|
||||
if (platform == Platform.NODE && sourceType == SourceType.COMMONJS_MODULE)
|
||||
textualExtractor.getTrapwriter().addTuple("isNodejs", toplevelLabel);
|
||||
|
||||
return Pair.make(toplevelLabel, loc);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class Main {
|
||||
* such a way that it may produce different tuples for the same file under the same
|
||||
* {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2019-01-29";
|
||||
public static final String EXTRACTOR_VERSION = "2019-02-04";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.declareModuleId('test');
|
||||
|
||||
export let x = 5;
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.module('test');
|
||||
var x = 5;
|
||||
exports = { x: x };
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.provide('test.x');
|
||||
|
||||
test.x = 5;
|
||||
@@ -0,0 +1,203 @@
|
||||
#10000=@"/googDotDeclareModuleId.js;sourcefile"
|
||||
files(#10000,"/googDotDeclareModuleId.js","googDotDeclareModuleId","js",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=@"script;{#10000},1,1"
|
||||
#20002=*
|
||||
lines(#20002,#20001,"goog.declareModuleId('test');","
|
||||
")
|
||||
#20003=@"loc,{#10000},1,1,1,29"
|
||||
locations_default(#20003,#10000,1,1,1,29)
|
||||
hasLocation(#20002,#20003)
|
||||
#20004=*
|
||||
lines(#20004,#20001,"","
|
||||
")
|
||||
#20005=@"loc,{#10000},2,1,2,0"
|
||||
locations_default(#20005,#10000,2,1,2,0)
|
||||
hasLocation(#20004,#20005)
|
||||
#20006=*
|
||||
lines(#20006,#20001,"export let x = 5;","
|
||||
")
|
||||
#20007=@"loc,{#10000},3,1,3,17"
|
||||
locations_default(#20007,#10000,3,1,3,17)
|
||||
hasLocation(#20006,#20007)
|
||||
numlines(#20001,3,2,0)
|
||||
#20008=*
|
||||
tokeninfo(#20008,6,#20001,0,"goog")
|
||||
#20009=@"loc,{#10000},1,1,1,4"
|
||||
locations_default(#20009,#10000,1,1,1,4)
|
||||
hasLocation(#20008,#20009)
|
||||
#20010=*
|
||||
tokeninfo(#20010,8,#20001,1,".")
|
||||
#20011=@"loc,{#10000},1,5,1,5"
|
||||
locations_default(#20011,#10000,1,5,1,5)
|
||||
hasLocation(#20010,#20011)
|
||||
#20012=*
|
||||
tokeninfo(#20012,6,#20001,2,"declareModuleId")
|
||||
#20013=@"loc,{#10000},1,6,1,20"
|
||||
locations_default(#20013,#10000,1,6,1,20)
|
||||
hasLocation(#20012,#20013)
|
||||
#20014=*
|
||||
tokeninfo(#20014,8,#20001,3,"(")
|
||||
#20015=@"loc,{#10000},1,21,1,21"
|
||||
locations_default(#20015,#10000,1,21,1,21)
|
||||
hasLocation(#20014,#20015)
|
||||
#20016=*
|
||||
tokeninfo(#20016,4,#20001,4,"'test'")
|
||||
#20017=@"loc,{#10000},1,22,1,27"
|
||||
locations_default(#20017,#10000,1,22,1,27)
|
||||
hasLocation(#20016,#20017)
|
||||
#20018=*
|
||||
tokeninfo(#20018,8,#20001,5,")")
|
||||
#20019=@"loc,{#10000},1,28,1,28"
|
||||
locations_default(#20019,#10000,1,28,1,28)
|
||||
hasLocation(#20018,#20019)
|
||||
#20020=*
|
||||
tokeninfo(#20020,8,#20001,6,";")
|
||||
#20021=@"loc,{#10000},1,29,1,29"
|
||||
locations_default(#20021,#10000,1,29,1,29)
|
||||
hasLocation(#20020,#20021)
|
||||
#20022=*
|
||||
tokeninfo(#20022,7,#20001,7,"export")
|
||||
#20023=@"loc,{#10000},3,1,3,6"
|
||||
locations_default(#20023,#10000,3,1,3,6)
|
||||
hasLocation(#20022,#20023)
|
||||
#20024=*
|
||||
tokeninfo(#20024,7,#20001,8,"let")
|
||||
#20025=@"loc,{#10000},3,8,3,10"
|
||||
locations_default(#20025,#10000,3,8,3,10)
|
||||
hasLocation(#20024,#20025)
|
||||
#20026=*
|
||||
tokeninfo(#20026,6,#20001,9,"x")
|
||||
#20027=@"loc,{#10000},3,12,3,12"
|
||||
locations_default(#20027,#10000,3,12,3,12)
|
||||
hasLocation(#20026,#20027)
|
||||
#20028=*
|
||||
tokeninfo(#20028,8,#20001,10,"=")
|
||||
#20029=@"loc,{#10000},3,14,3,14"
|
||||
locations_default(#20029,#10000,3,14,3,14)
|
||||
hasLocation(#20028,#20029)
|
||||
#20030=*
|
||||
tokeninfo(#20030,3,#20001,11,"5")
|
||||
#20031=@"loc,{#10000},3,16,3,16"
|
||||
locations_default(#20031,#10000,3,16,3,16)
|
||||
hasLocation(#20030,#20031)
|
||||
#20032=*
|
||||
tokeninfo(#20032,8,#20001,12,";")
|
||||
#20033=@"loc,{#10000},3,17,3,17"
|
||||
locations_default(#20033,#10000,3,17,3,17)
|
||||
hasLocation(#20032,#20033)
|
||||
#20034=*
|
||||
tokeninfo(#20034,0,#20001,13,"")
|
||||
#20035=@"loc,{#10000},4,1,4,0"
|
||||
locations_default(#20035,#10000,4,1,4,0)
|
||||
hasLocation(#20034,#20035)
|
||||
toplevels(#20001,0)
|
||||
#20036=@"loc,{#10000},1,1,4,0"
|
||||
locations_default(#20036,#10000,1,1,4,0)
|
||||
hasLocation(#20001,#20036)
|
||||
#20037=@"module;{#10000},1,1"
|
||||
scopes(#20037,3)
|
||||
scopenodes(#20001,#20037)
|
||||
scopenesting(#20037,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20038=@"var;{x};{#20037}"
|
||||
variables(#20038,"x",#20037)
|
||||
#20039=*
|
||||
stmts(#20039,2,#20001,0,"goog.de ... test');")
|
||||
hasLocation(#20039,#20003)
|
||||
stmtContainers(#20039,#20001)
|
||||
#20040=*
|
||||
exprs(#20040,13,#20039,0,"goog.de ... 'test')")
|
||||
#20041=@"loc,{#10000},1,1,1,28"
|
||||
locations_default(#20041,#10000,1,1,1,28)
|
||||
hasLocation(#20040,#20041)
|
||||
enclosingStmt(#20040,#20039)
|
||||
exprContainers(#20040,#20001)
|
||||
#20042=*
|
||||
exprs(#20042,14,#20040,-1,"goog.declareModuleId")
|
||||
#20043=@"loc,{#10000},1,1,1,20"
|
||||
locations_default(#20043,#10000,1,1,1,20)
|
||||
hasLocation(#20042,#20043)
|
||||
enclosingStmt(#20042,#20039)
|
||||
exprContainers(#20042,#20001)
|
||||
#20044=*
|
||||
exprs(#20044,79,#20042,0,"goog")
|
||||
hasLocation(#20044,#20009)
|
||||
enclosingStmt(#20044,#20039)
|
||||
exprContainers(#20044,#20001)
|
||||
literals("goog","goog",#20044)
|
||||
#20045=@"var;{goog};{#20000}"
|
||||
variables(#20045,"goog",#20000)
|
||||
bind(#20044,#20045)
|
||||
#20046=*
|
||||
exprs(#20046,0,#20042,1,"declareModuleId")
|
||||
hasLocation(#20046,#20013)
|
||||
enclosingStmt(#20046,#20039)
|
||||
exprContainers(#20046,#20001)
|
||||
literals("declareModuleId","declareModuleId",#20046)
|
||||
#20047=*
|
||||
exprs(#20047,4,#20040,0,"'test'")
|
||||
hasLocation(#20047,#20017)
|
||||
enclosingStmt(#20047,#20039)
|
||||
exprContainers(#20047,#20001)
|
||||
literals("test","'test'",#20047)
|
||||
#20048=*
|
||||
stmts(#20048,30,#20001,1,"export let x = 5;")
|
||||
hasLocation(#20048,#20007)
|
||||
stmtContainers(#20048,#20001)
|
||||
#20049=*
|
||||
stmts(#20049,23,#20048,-1,"let x = 5;")
|
||||
#20050=@"loc,{#10000},3,8,3,17"
|
||||
locations_default(#20050,#10000,3,8,3,17)
|
||||
hasLocation(#20049,#20050)
|
||||
stmtContainers(#20049,#20001)
|
||||
#20051=*
|
||||
exprs(#20051,64,#20049,0,"x = 5")
|
||||
#20052=@"loc,{#10000},3,12,3,16"
|
||||
locations_default(#20052,#10000,3,12,3,16)
|
||||
hasLocation(#20051,#20052)
|
||||
enclosingStmt(#20051,#20049)
|
||||
exprContainers(#20051,#20001)
|
||||
#20053=*
|
||||
exprs(#20053,78,#20051,0,"x")
|
||||
hasLocation(#20053,#20027)
|
||||
enclosingStmt(#20053,#20049)
|
||||
exprContainers(#20053,#20001)
|
||||
literals("x","x",#20053)
|
||||
decl(#20053,#20038)
|
||||
#20054=*
|
||||
exprs(#20054,3,#20051,1,"5")
|
||||
hasLocation(#20054,#20031)
|
||||
enclosingStmt(#20054,#20049)
|
||||
exprContainers(#20054,#20001)
|
||||
literals("5","5",#20054)
|
||||
#20055=*
|
||||
entry_cfg_node(#20055,#20001)
|
||||
#20056=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20056,#10000,1,1,1,0)
|
||||
hasLocation(#20055,#20056)
|
||||
#20057=*
|
||||
exit_cfg_node(#20057,#20001)
|
||||
hasLocation(#20057,#20035)
|
||||
successor(#20048,#20049)
|
||||
successor(#20049,#20053)
|
||||
successor(#20054,#20051)
|
||||
successor(#20053,#20054)
|
||||
successor(#20051,#20057)
|
||||
successor(#20039,#20044)
|
||||
successor(#20047,#20040)
|
||||
successor(#20046,#20042)
|
||||
successor(#20044,#20046)
|
||||
successor(#20042,#20047)
|
||||
successor(#20040,#20048)
|
||||
successor(#20055,#20039)
|
||||
numlines(#10000,3,2,0)
|
||||
filetype(#10000,"javascript")
|
||||
@@ -0,0 +1,283 @@
|
||||
#10000=@"/googDotModule.js;sourcefile"
|
||||
files(#10000,"/googDotModule.js","googDotModule","js",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=@"script;{#10000},1,1"
|
||||
#20002=*
|
||||
lines(#20002,#20001,"goog.module('test');","
|
||||
")
|
||||
#20003=@"loc,{#10000},1,1,1,20"
|
||||
locations_default(#20003,#10000,1,1,1,20)
|
||||
hasLocation(#20002,#20003)
|
||||
#20004=*
|
||||
lines(#20004,#20001,"var x = 5;","
|
||||
")
|
||||
#20005=@"loc,{#10000},2,1,2,10"
|
||||
locations_default(#20005,#10000,2,1,2,10)
|
||||
hasLocation(#20004,#20005)
|
||||
#20006=*
|
||||
lines(#20006,#20001,"exports = { x: x };","
|
||||
")
|
||||
#20007=@"loc,{#10000},3,1,3,19"
|
||||
locations_default(#20007,#10000,3,1,3,19)
|
||||
hasLocation(#20006,#20007)
|
||||
numlines(#20001,3,3,0)
|
||||
#20008=*
|
||||
tokeninfo(#20008,6,#20001,0,"goog")
|
||||
#20009=@"loc,{#10000},1,1,1,4"
|
||||
locations_default(#20009,#10000,1,1,1,4)
|
||||
hasLocation(#20008,#20009)
|
||||
#20010=*
|
||||
tokeninfo(#20010,8,#20001,1,".")
|
||||
#20011=@"loc,{#10000},1,5,1,5"
|
||||
locations_default(#20011,#10000,1,5,1,5)
|
||||
hasLocation(#20010,#20011)
|
||||
#20012=*
|
||||
tokeninfo(#20012,6,#20001,2,"module")
|
||||
#20013=@"loc,{#10000},1,6,1,11"
|
||||
locations_default(#20013,#10000,1,6,1,11)
|
||||
hasLocation(#20012,#20013)
|
||||
#20014=*
|
||||
tokeninfo(#20014,8,#20001,3,"(")
|
||||
#20015=@"loc,{#10000},1,12,1,12"
|
||||
locations_default(#20015,#10000,1,12,1,12)
|
||||
hasLocation(#20014,#20015)
|
||||
#20016=*
|
||||
tokeninfo(#20016,4,#20001,4,"'test'")
|
||||
#20017=@"loc,{#10000},1,13,1,18"
|
||||
locations_default(#20017,#10000,1,13,1,18)
|
||||
hasLocation(#20016,#20017)
|
||||
#20018=*
|
||||
tokeninfo(#20018,8,#20001,5,")")
|
||||
#20019=@"loc,{#10000},1,19,1,19"
|
||||
locations_default(#20019,#10000,1,19,1,19)
|
||||
hasLocation(#20018,#20019)
|
||||
#20020=*
|
||||
tokeninfo(#20020,8,#20001,6,";")
|
||||
#20021=@"loc,{#10000},1,20,1,20"
|
||||
locations_default(#20021,#10000,1,20,1,20)
|
||||
hasLocation(#20020,#20021)
|
||||
#20022=*
|
||||
tokeninfo(#20022,7,#20001,7,"var")
|
||||
#20023=@"loc,{#10000},2,1,2,3"
|
||||
locations_default(#20023,#10000,2,1,2,3)
|
||||
hasLocation(#20022,#20023)
|
||||
#20024=*
|
||||
tokeninfo(#20024,6,#20001,8,"x")
|
||||
#20025=@"loc,{#10000},2,5,2,5"
|
||||
locations_default(#20025,#10000,2,5,2,5)
|
||||
hasLocation(#20024,#20025)
|
||||
#20026=*
|
||||
tokeninfo(#20026,8,#20001,9,"=")
|
||||
#20027=@"loc,{#10000},2,7,2,7"
|
||||
locations_default(#20027,#10000,2,7,2,7)
|
||||
hasLocation(#20026,#20027)
|
||||
#20028=*
|
||||
tokeninfo(#20028,3,#20001,10,"5")
|
||||
#20029=@"loc,{#10000},2,9,2,9"
|
||||
locations_default(#20029,#10000,2,9,2,9)
|
||||
hasLocation(#20028,#20029)
|
||||
#20030=*
|
||||
tokeninfo(#20030,8,#20001,11,";")
|
||||
#20031=@"loc,{#10000},2,10,2,10"
|
||||
locations_default(#20031,#10000,2,10,2,10)
|
||||
hasLocation(#20030,#20031)
|
||||
#20032=*
|
||||
tokeninfo(#20032,6,#20001,12,"exports")
|
||||
#20033=@"loc,{#10000},3,1,3,7"
|
||||
locations_default(#20033,#10000,3,1,3,7)
|
||||
hasLocation(#20032,#20033)
|
||||
#20034=*
|
||||
tokeninfo(#20034,8,#20001,13,"=")
|
||||
#20035=@"loc,{#10000},3,9,3,9"
|
||||
locations_default(#20035,#10000,3,9,3,9)
|
||||
hasLocation(#20034,#20035)
|
||||
#20036=*
|
||||
tokeninfo(#20036,8,#20001,14,"{")
|
||||
#20037=@"loc,{#10000},3,11,3,11"
|
||||
locations_default(#20037,#10000,3,11,3,11)
|
||||
hasLocation(#20036,#20037)
|
||||
#20038=*
|
||||
tokeninfo(#20038,6,#20001,15,"x")
|
||||
#20039=@"loc,{#10000},3,13,3,13"
|
||||
locations_default(#20039,#10000,3,13,3,13)
|
||||
hasLocation(#20038,#20039)
|
||||
#20040=*
|
||||
tokeninfo(#20040,8,#20001,16,":")
|
||||
#20041=@"loc,{#10000},3,14,3,14"
|
||||
locations_default(#20041,#10000,3,14,3,14)
|
||||
hasLocation(#20040,#20041)
|
||||
#20042=*
|
||||
tokeninfo(#20042,6,#20001,17,"x")
|
||||
#20043=@"loc,{#10000},3,16,3,16"
|
||||
locations_default(#20043,#10000,3,16,3,16)
|
||||
hasLocation(#20042,#20043)
|
||||
#20044=*
|
||||
tokeninfo(#20044,8,#20001,18,"}")
|
||||
#20045=@"loc,{#10000},3,18,3,18"
|
||||
locations_default(#20045,#10000,3,18,3,18)
|
||||
hasLocation(#20044,#20045)
|
||||
#20046=*
|
||||
tokeninfo(#20046,8,#20001,19,";")
|
||||
#20047=@"loc,{#10000},3,19,3,19"
|
||||
locations_default(#20047,#10000,3,19,3,19)
|
||||
hasLocation(#20046,#20047)
|
||||
#20048=*
|
||||
tokeninfo(#20048,0,#20001,20,"")
|
||||
#20049=@"loc,{#10000},4,1,4,0"
|
||||
locations_default(#20049,#10000,4,1,4,0)
|
||||
hasLocation(#20048,#20049)
|
||||
toplevels(#20001,0)
|
||||
#20050=@"loc,{#10000},1,1,4,0"
|
||||
locations_default(#20050,#10000,1,1,4,0)
|
||||
hasLocation(#20001,#20050)
|
||||
#20051=@"module;{#10000},1,1"
|
||||
scopes(#20051,3)
|
||||
scopenodes(#20001,#20051)
|
||||
scopenesting(#20051,#20000)
|
||||
#20052=@"var;{exports};{#20051}"
|
||||
variables(#20052,"exports",#20051)
|
||||
isModule(#20001)
|
||||
isClosureModule(#20001)
|
||||
#20053=@"var;{x};{#20051}"
|
||||
variables(#20053,"x",#20051)
|
||||
#20054=*
|
||||
stmts(#20054,2,#20001,0,"goog.module('test');")
|
||||
hasLocation(#20054,#20003)
|
||||
stmtContainers(#20054,#20001)
|
||||
#20055=*
|
||||
exprs(#20055,13,#20054,0,"goog.module('test')")
|
||||
#20056=@"loc,{#10000},1,1,1,19"
|
||||
locations_default(#20056,#10000,1,1,1,19)
|
||||
hasLocation(#20055,#20056)
|
||||
enclosingStmt(#20055,#20054)
|
||||
exprContainers(#20055,#20001)
|
||||
#20057=*
|
||||
exprs(#20057,14,#20055,-1,"goog.module")
|
||||
#20058=@"loc,{#10000},1,1,1,11"
|
||||
locations_default(#20058,#10000,1,1,1,11)
|
||||
hasLocation(#20057,#20058)
|
||||
enclosingStmt(#20057,#20054)
|
||||
exprContainers(#20057,#20001)
|
||||
#20059=*
|
||||
exprs(#20059,79,#20057,0,"goog")
|
||||
hasLocation(#20059,#20009)
|
||||
enclosingStmt(#20059,#20054)
|
||||
exprContainers(#20059,#20001)
|
||||
literals("goog","goog",#20059)
|
||||
#20060=@"var;{goog};{#20000}"
|
||||
variables(#20060,"goog",#20000)
|
||||
bind(#20059,#20060)
|
||||
#20061=*
|
||||
exprs(#20061,0,#20057,1,"module")
|
||||
hasLocation(#20061,#20013)
|
||||
enclosingStmt(#20061,#20054)
|
||||
exprContainers(#20061,#20001)
|
||||
literals("module","module",#20061)
|
||||
#20062=*
|
||||
exprs(#20062,4,#20055,0,"'test'")
|
||||
hasLocation(#20062,#20017)
|
||||
enclosingStmt(#20062,#20054)
|
||||
exprContainers(#20062,#20001)
|
||||
literals("test","'test'",#20062)
|
||||
#20063=*
|
||||
stmts(#20063,18,#20001,1,"var x = 5;")
|
||||
hasLocation(#20063,#20005)
|
||||
stmtContainers(#20063,#20001)
|
||||
#20064=*
|
||||
exprs(#20064,64,#20063,0,"x = 5")
|
||||
#20065=@"loc,{#10000},2,5,2,9"
|
||||
locations_default(#20065,#10000,2,5,2,9)
|
||||
hasLocation(#20064,#20065)
|
||||
enclosingStmt(#20064,#20063)
|
||||
exprContainers(#20064,#20001)
|
||||
#20066=*
|
||||
exprs(#20066,78,#20064,0,"x")
|
||||
hasLocation(#20066,#20025)
|
||||
enclosingStmt(#20066,#20063)
|
||||
exprContainers(#20066,#20001)
|
||||
literals("x","x",#20066)
|
||||
decl(#20066,#20053)
|
||||
#20067=*
|
||||
exprs(#20067,3,#20064,1,"5")
|
||||
hasLocation(#20067,#20029)
|
||||
enclosingStmt(#20067,#20063)
|
||||
exprContainers(#20067,#20001)
|
||||
literals("5","5",#20067)
|
||||
#20068=*
|
||||
stmts(#20068,2,#20001,2,"exports = { x: x };")
|
||||
hasLocation(#20068,#20007)
|
||||
stmtContainers(#20068,#20001)
|
||||
#20069=*
|
||||
exprs(#20069,47,#20068,0,"exports = { x: x }")
|
||||
#20070=@"loc,{#10000},3,1,3,18"
|
||||
locations_default(#20070,#10000,3,1,3,18)
|
||||
hasLocation(#20069,#20070)
|
||||
enclosingStmt(#20069,#20068)
|
||||
exprContainers(#20069,#20001)
|
||||
#20071=*
|
||||
exprs(#20071,79,#20069,0,"exports")
|
||||
hasLocation(#20071,#20033)
|
||||
enclosingStmt(#20071,#20068)
|
||||
exprContainers(#20071,#20001)
|
||||
literals("exports","exports",#20071)
|
||||
bind(#20071,#20052)
|
||||
#20072=*
|
||||
exprs(#20072,8,#20069,1,"{ x: x }")
|
||||
#20073=@"loc,{#10000},3,11,3,18"
|
||||
locations_default(#20073,#10000,3,11,3,18)
|
||||
hasLocation(#20072,#20073)
|
||||
enclosingStmt(#20072,#20068)
|
||||
exprContainers(#20072,#20001)
|
||||
#20074=*
|
||||
properties(#20074,#20072,0,0,"x: x")
|
||||
#20075=@"loc,{#10000},3,13,3,16"
|
||||
locations_default(#20075,#10000,3,13,3,16)
|
||||
hasLocation(#20074,#20075)
|
||||
#20076=*
|
||||
exprs(#20076,0,#20074,0,"x")
|
||||
hasLocation(#20076,#20039)
|
||||
enclosingStmt(#20076,#20068)
|
||||
exprContainers(#20076,#20001)
|
||||
literals("x","x",#20076)
|
||||
#20077=*
|
||||
exprs(#20077,79,#20074,1,"x")
|
||||
hasLocation(#20077,#20043)
|
||||
enclosingStmt(#20077,#20068)
|
||||
exprContainers(#20077,#20001)
|
||||
literals("x","x",#20077)
|
||||
bind(#20077,#20053)
|
||||
#20078=*
|
||||
entry_cfg_node(#20078,#20001)
|
||||
#20079=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20079,#10000,1,1,1,0)
|
||||
hasLocation(#20078,#20079)
|
||||
#20080=*
|
||||
exit_cfg_node(#20080,#20001)
|
||||
hasLocation(#20080,#20049)
|
||||
successor(#20068,#20071)
|
||||
successor(#20072,#20076)
|
||||
successor(#20077,#20074)
|
||||
successor(#20076,#20077)
|
||||
successor(#20074,#20069)
|
||||
successor(#20071,#20072)
|
||||
successor(#20069,#20080)
|
||||
successor(#20063,#20066)
|
||||
successor(#20067,#20064)
|
||||
successor(#20066,#20067)
|
||||
successor(#20064,#20068)
|
||||
successor(#20054,#20059)
|
||||
successor(#20062,#20055)
|
||||
successor(#20061,#20057)
|
||||
successor(#20059,#20061)
|
||||
successor(#20057,#20062)
|
||||
successor(#20055,#20063)
|
||||
successor(#20078,#20054)
|
||||
numlines(#10000,3,3,0)
|
||||
filetype(#10000,"javascript")
|
||||
@@ -0,0 +1,205 @@
|
||||
#10000=@"/googDotProvide.js;sourcefile"
|
||||
files(#10000,"/googDotProvide.js","googDotProvide","js",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=@"script;{#10000},1,1"
|
||||
#20002=*
|
||||
lines(#20002,#20001,"goog.provide('test.x');","
|
||||
")
|
||||
#20003=@"loc,{#10000},1,1,1,23"
|
||||
locations_default(#20003,#10000,1,1,1,23)
|
||||
hasLocation(#20002,#20003)
|
||||
#20004=*
|
||||
lines(#20004,#20001,"","
|
||||
")
|
||||
#20005=@"loc,{#10000},2,1,2,0"
|
||||
locations_default(#20005,#10000,2,1,2,0)
|
||||
hasLocation(#20004,#20005)
|
||||
#20006=*
|
||||
lines(#20006,#20001,"test.x = 5;","
|
||||
")
|
||||
#20007=@"loc,{#10000},3,1,3,11"
|
||||
locations_default(#20007,#10000,3,1,3,11)
|
||||
hasLocation(#20006,#20007)
|
||||
numlines(#20001,3,2,0)
|
||||
#20008=*
|
||||
tokeninfo(#20008,6,#20001,0,"goog")
|
||||
#20009=@"loc,{#10000},1,1,1,4"
|
||||
locations_default(#20009,#10000,1,1,1,4)
|
||||
hasLocation(#20008,#20009)
|
||||
#20010=*
|
||||
tokeninfo(#20010,8,#20001,1,".")
|
||||
#20011=@"loc,{#10000},1,5,1,5"
|
||||
locations_default(#20011,#10000,1,5,1,5)
|
||||
hasLocation(#20010,#20011)
|
||||
#20012=*
|
||||
tokeninfo(#20012,6,#20001,2,"provide")
|
||||
#20013=@"loc,{#10000},1,6,1,12"
|
||||
locations_default(#20013,#10000,1,6,1,12)
|
||||
hasLocation(#20012,#20013)
|
||||
#20014=*
|
||||
tokeninfo(#20014,8,#20001,3,"(")
|
||||
#20015=@"loc,{#10000},1,13,1,13"
|
||||
locations_default(#20015,#10000,1,13,1,13)
|
||||
hasLocation(#20014,#20015)
|
||||
#20016=*
|
||||
tokeninfo(#20016,4,#20001,4,"'test.x'")
|
||||
#20017=@"loc,{#10000},1,14,1,21"
|
||||
locations_default(#20017,#10000,1,14,1,21)
|
||||
hasLocation(#20016,#20017)
|
||||
#20018=*
|
||||
tokeninfo(#20018,8,#20001,5,")")
|
||||
#20019=@"loc,{#10000},1,22,1,22"
|
||||
locations_default(#20019,#10000,1,22,1,22)
|
||||
hasLocation(#20018,#20019)
|
||||
#20020=*
|
||||
tokeninfo(#20020,8,#20001,6,";")
|
||||
#20021=@"loc,{#10000},1,23,1,23"
|
||||
locations_default(#20021,#10000,1,23,1,23)
|
||||
hasLocation(#20020,#20021)
|
||||
#20022=*
|
||||
tokeninfo(#20022,6,#20001,7,"test")
|
||||
#20023=@"loc,{#10000},3,1,3,4"
|
||||
locations_default(#20023,#10000,3,1,3,4)
|
||||
hasLocation(#20022,#20023)
|
||||
#20024=*
|
||||
tokeninfo(#20024,8,#20001,8,".")
|
||||
#20025=@"loc,{#10000},3,5,3,5"
|
||||
locations_default(#20025,#10000,3,5,3,5)
|
||||
hasLocation(#20024,#20025)
|
||||
#20026=*
|
||||
tokeninfo(#20026,6,#20001,9,"x")
|
||||
#20027=@"loc,{#10000},3,6,3,6"
|
||||
locations_default(#20027,#10000,3,6,3,6)
|
||||
hasLocation(#20026,#20027)
|
||||
#20028=*
|
||||
tokeninfo(#20028,8,#20001,10,"=")
|
||||
#20029=@"loc,{#10000},3,8,3,8"
|
||||
locations_default(#20029,#10000,3,8,3,8)
|
||||
hasLocation(#20028,#20029)
|
||||
#20030=*
|
||||
tokeninfo(#20030,3,#20001,11,"5")
|
||||
#20031=@"loc,{#10000},3,10,3,10"
|
||||
locations_default(#20031,#10000,3,10,3,10)
|
||||
hasLocation(#20030,#20031)
|
||||
#20032=*
|
||||
tokeninfo(#20032,8,#20001,12,";")
|
||||
#20033=@"loc,{#10000},3,11,3,11"
|
||||
locations_default(#20033,#10000,3,11,3,11)
|
||||
hasLocation(#20032,#20033)
|
||||
#20034=*
|
||||
tokeninfo(#20034,0,#20001,13,"")
|
||||
#20035=@"loc,{#10000},4,1,4,0"
|
||||
locations_default(#20035,#10000,4,1,4,0)
|
||||
hasLocation(#20034,#20035)
|
||||
toplevels(#20001,0)
|
||||
#20036=@"loc,{#10000},1,1,4,0"
|
||||
locations_default(#20036,#10000,1,1,4,0)
|
||||
hasLocation(#20001,#20036)
|
||||
#20037=*
|
||||
stmts(#20037,2,#20001,0,"goog.pr ... st.x');")
|
||||
hasLocation(#20037,#20003)
|
||||
stmtContainers(#20037,#20001)
|
||||
#20038=*
|
||||
exprs(#20038,13,#20037,0,"goog.pr ... est.x')")
|
||||
#20039=@"loc,{#10000},1,1,1,22"
|
||||
locations_default(#20039,#10000,1,1,1,22)
|
||||
hasLocation(#20038,#20039)
|
||||
enclosingStmt(#20038,#20037)
|
||||
exprContainers(#20038,#20001)
|
||||
#20040=*
|
||||
exprs(#20040,14,#20038,-1,"goog.provide")
|
||||
#20041=@"loc,{#10000},1,1,1,12"
|
||||
locations_default(#20041,#10000,1,1,1,12)
|
||||
hasLocation(#20040,#20041)
|
||||
enclosingStmt(#20040,#20037)
|
||||
exprContainers(#20040,#20001)
|
||||
#20042=*
|
||||
exprs(#20042,79,#20040,0,"goog")
|
||||
hasLocation(#20042,#20009)
|
||||
enclosingStmt(#20042,#20037)
|
||||
exprContainers(#20042,#20001)
|
||||
literals("goog","goog",#20042)
|
||||
#20043=@"var;{goog};{#20000}"
|
||||
variables(#20043,"goog",#20000)
|
||||
bind(#20042,#20043)
|
||||
#20044=*
|
||||
exprs(#20044,0,#20040,1,"provide")
|
||||
hasLocation(#20044,#20013)
|
||||
enclosingStmt(#20044,#20037)
|
||||
exprContainers(#20044,#20001)
|
||||
literals("provide","provide",#20044)
|
||||
#20045=*
|
||||
exprs(#20045,4,#20038,0,"'test.x'")
|
||||
hasLocation(#20045,#20017)
|
||||
enclosingStmt(#20045,#20037)
|
||||
exprContainers(#20045,#20001)
|
||||
literals("test.x","'test.x'",#20045)
|
||||
#20046=*
|
||||
stmts(#20046,2,#20001,1,"test.x = 5;")
|
||||
hasLocation(#20046,#20007)
|
||||
stmtContainers(#20046,#20001)
|
||||
#20047=*
|
||||
exprs(#20047,47,#20046,0,"test.x = 5")
|
||||
#20048=@"loc,{#10000},3,1,3,10"
|
||||
locations_default(#20048,#10000,3,1,3,10)
|
||||
hasLocation(#20047,#20048)
|
||||
enclosingStmt(#20047,#20046)
|
||||
exprContainers(#20047,#20001)
|
||||
#20049=*
|
||||
exprs(#20049,14,#20047,0,"test.x")
|
||||
#20050=@"loc,{#10000},3,1,3,6"
|
||||
locations_default(#20050,#10000,3,1,3,6)
|
||||
hasLocation(#20049,#20050)
|
||||
enclosingStmt(#20049,#20046)
|
||||
exprContainers(#20049,#20001)
|
||||
#20051=*
|
||||
exprs(#20051,79,#20049,0,"test")
|
||||
hasLocation(#20051,#20023)
|
||||
enclosingStmt(#20051,#20046)
|
||||
exprContainers(#20051,#20001)
|
||||
literals("test","test",#20051)
|
||||
#20052=@"var;{test};{#20000}"
|
||||
variables(#20052,"test",#20000)
|
||||
bind(#20051,#20052)
|
||||
#20053=*
|
||||
exprs(#20053,0,#20049,1,"x")
|
||||
hasLocation(#20053,#20027)
|
||||
enclosingStmt(#20053,#20046)
|
||||
exprContainers(#20053,#20001)
|
||||
literals("x","x",#20053)
|
||||
#20054=*
|
||||
exprs(#20054,3,#20047,1,"5")
|
||||
hasLocation(#20054,#20031)
|
||||
enclosingStmt(#20054,#20046)
|
||||
exprContainers(#20054,#20001)
|
||||
literals("5","5",#20054)
|
||||
#20055=*
|
||||
entry_cfg_node(#20055,#20001)
|
||||
#20056=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20056,#10000,1,1,1,0)
|
||||
hasLocation(#20055,#20056)
|
||||
#20057=*
|
||||
exit_cfg_node(#20057,#20001)
|
||||
hasLocation(#20057,#20035)
|
||||
successor(#20046,#20051)
|
||||
successor(#20054,#20047)
|
||||
successor(#20053,#20049)
|
||||
successor(#20051,#20053)
|
||||
successor(#20049,#20054)
|
||||
successor(#20047,#20057)
|
||||
successor(#20037,#20042)
|
||||
successor(#20045,#20038)
|
||||
successor(#20044,#20040)
|
||||
successor(#20042,#20044)
|
||||
successor(#20040,#20045)
|
||||
successor(#20038,#20046)
|
||||
successor(#20055,#20037)
|
||||
numlines(#10000,3,2,0)
|
||||
filetype(#10000,"javascript")
|
||||
@@ -57,6 +57,7 @@ scopes(#20018,3)
|
||||
scopenodes(#20001,#20018)
|
||||
scopenesting(#20018,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20019=@"var;{x};{#20018}"
|
||||
variables(#20019,"x",#20018)
|
||||
#20020=*
|
||||
|
||||
@@ -85,6 +85,7 @@ scopes(#20029,3)
|
||||
scopenodes(#20001,#20029)
|
||||
scopenesting(#20029,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20030=@"var;{f};{#20029}"
|
||||
variables(#20030,"f",#20029)
|
||||
#20031=*
|
||||
|
||||
@@ -55,6 +55,7 @@ scopes(#20017,3)
|
||||
scopenodes(#20001,#20017)
|
||||
scopenesting(#20017,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20018=*
|
||||
stmts(#20018,29,#20001,0,"export ... lass {}")
|
||||
hasLocation(#20018,#20003)
|
||||
|
||||
@@ -67,6 +67,7 @@ scopes(#20022,3)
|
||||
scopenodes(#20001,#20022)
|
||||
scopenesting(#20022,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20023=@"var;{f};{#20022}"
|
||||
variables(#20023,"f",#20022)
|
||||
#20024=*
|
||||
|
||||
@@ -72,6 +72,7 @@ scopes(#20024,3)
|
||||
scopenodes(#20001,#20024)
|
||||
scopenesting(#20024,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20025=@"var;{f};{#20024}"
|
||||
variables(#20025,"f",#20024)
|
||||
#20026=*
|
||||
|
||||
@@ -67,6 +67,7 @@ scopes(#20022,3)
|
||||
scopenodes(#20001,#20022)
|
||||
scopenesting(#20022,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20023=*
|
||||
stmts(#20023,29,#20001,0,"export ... n () {}")
|
||||
#20024=@"loc,{#10000},1,1,1,29"
|
||||
|
||||
@@ -125,6 +125,7 @@ scopes(#20045,3)
|
||||
scopenodes(#20001,#20045)
|
||||
scopenesting(#20045,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20046=@"var;{x};{#20045}"
|
||||
variables(#20046,"x",#20045)
|
||||
#20047=@"var;{y};{#20045}"
|
||||
|
||||
@@ -52,6 +52,7 @@ scopes(#20016,3)
|
||||
scopenodes(#20001,#20016)
|
||||
scopenesting(#20016,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20017=*
|
||||
stmts(#20017,28,#20001,0,"export * from 'foo';")
|
||||
hasLocation(#20017,#20003)
|
||||
|
||||
@@ -82,6 +82,7 @@ scopes(#20028,3)
|
||||
scopenodes(#20001,#20028)
|
||||
scopenesting(#20028,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20029=*
|
||||
stmts(#20029,30,#20001,0,"export ... 'foo';")
|
||||
hasLocation(#20029,#20003)
|
||||
|
||||
@@ -75,6 +75,7 @@ scopes(#20025,3)
|
||||
scopenodes(#20001,#20025)
|
||||
scopenesting(#20025,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20026=*
|
||||
stmts(#20026,2,#20001,0,"foo = 42;")
|
||||
hasLocation(#20026,#20003)
|
||||
|
||||
@@ -75,6 +75,7 @@ scopes(#20025,3)
|
||||
scopenodes(#20001,#20025)
|
||||
scopenesting(#20025,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20026=@"var;{C};{#20025}"
|
||||
variables(#20026,"C",#20025)
|
||||
#20027=@"local_type_name;{C};{#20025}"
|
||||
|
||||
@@ -52,6 +52,7 @@ scopes(#20016,3)
|
||||
scopenodes(#20001,#20016)
|
||||
scopenesting(#20016,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20017=@"var;{x};{#20016}"
|
||||
variables(#20017,"x",#20016)
|
||||
#20018=@"local_type_name;{x};{#20016}"
|
||||
|
||||
@@ -62,6 +62,7 @@ scopes(#20020,3)
|
||||
scopenodes(#20001,#20020)
|
||||
scopenesting(#20020,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20021=@"var;{y};{#20020}"
|
||||
variables(#20021,"y",#20020)
|
||||
#20022=@"local_type_name;{y};{#20020}"
|
||||
|
||||
@@ -72,6 +72,7 @@ scopes(#20024,3)
|
||||
scopenodes(#20001,#20024)
|
||||
scopenesting(#20024,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20025=@"var;{z};{#20024}"
|
||||
variables(#20025,"z",#20024)
|
||||
#20026=@"local_type_name;{z};{#20024}"
|
||||
|
||||
@@ -82,6 +82,7 @@ scopes(#20028,3)
|
||||
scopenodes(#20001,#20028)
|
||||
scopenesting(#20028,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20029=@"var;{x};{#20028}"
|
||||
variables(#20029,"x",#20028)
|
||||
#20030=@"var;{z};{#20028}"
|
||||
|
||||
@@ -62,6 +62,7 @@ scopes(#20020,3)
|
||||
scopenodes(#20001,#20020)
|
||||
scopenesting(#20020,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20021=@"var;{foo};{#20020}"
|
||||
variables(#20021,"foo",#20020)
|
||||
#20022=@"local_namespace_name;{foo};{#20020}"
|
||||
|
||||
@@ -42,6 +42,7 @@ scopes(#20012,3)
|
||||
scopenodes(#20001,#20012)
|
||||
scopenesting(#20012,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20013=*
|
||||
stmts(#20013,27,#20001,0,"import 'foo';")
|
||||
hasLocation(#20013,#20003)
|
||||
|
||||
@@ -126,6 +126,7 @@ scopes(#20045,3)
|
||||
scopenodes(#20001,#20045)
|
||||
scopenesting(#20045,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20046=@"var;{x};{#20045}"
|
||||
variables(#20046,"x",#20045)
|
||||
#20047=@"var;{z};{#20045}"
|
||||
|
||||
@@ -179,6 +179,7 @@ scopes(#20064,3)
|
||||
scopenodes(#20001,#20064)
|
||||
scopenesting(#20064,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20065=@"var;{x};{#20064}"
|
||||
variables(#20065,"x",#20064)
|
||||
#20066=@"var;{y};{#20064}"
|
||||
|
||||
@@ -196,6 +196,7 @@ scopes(#20069,3)
|
||||
scopenodes(#20001,#20069)
|
||||
scopenesting(#20069,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20070=@"var;{foo};{#20069}"
|
||||
variables(#20070,"foo",#20069)
|
||||
#20071=*
|
||||
|
||||
@@ -80,6 +80,7 @@ scopes(#20027,3)
|
||||
scopenodes(#20001,#20027)
|
||||
scopenesting(#20027,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20028=@"var;{f};{#20027}"
|
||||
variables(#20028,"f",#20027)
|
||||
#20029=*
|
||||
|
||||
@@ -75,6 +75,7 @@ scopes(#20025,3)
|
||||
scopenodes(#20001,#20025)
|
||||
scopenesting(#20025,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20026=*
|
||||
stmts(#20026,29,#20001,0,"export ... n () {}")
|
||||
#20027=@"loc,{#10000},1,1,1,35"
|
||||
|
||||
@@ -192,6 +192,7 @@ scopes(#20071,3)
|
||||
scopenodes(#20001,#20071)
|
||||
scopenesting(#20071,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20072=*
|
||||
stmts(#20072,2,#20001,0,"import(""m"");")
|
||||
hasLocation(#20072,#20003)
|
||||
|
||||
@@ -65,6 +65,7 @@ scopes(#20021,3)
|
||||
scopenodes(#20001,#20021)
|
||||
scopenesting(#20021,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20022=*
|
||||
stmts(#20022,2,#20001,0,"console ... ES6"");")
|
||||
hasLocation(#20022,#20003)
|
||||
|
||||
@@ -65,6 +65,7 @@ scopes(#20021,3)
|
||||
scopenodes(#20001,#20021)
|
||||
scopenesting(#20021,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20022=*
|
||||
stmts(#20022,2,#20001,0,"console ... o ES"");")
|
||||
hasLocation(#20022,#20003)
|
||||
|
||||
@@ -77,6 +77,7 @@ scopes(#20026,3)
|
||||
scopenodes(#20001,#20026)
|
||||
scopenesting(#20026,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20027=*
|
||||
entry_cfg_node(#20027,#20001)
|
||||
#20028=@"loc,{#10000},1,1,1,0"
|
||||
|
||||
@@ -90,6 +90,7 @@ scopes(#20031,3)
|
||||
scopenodes(#20001,#20031)
|
||||
scopenesting(#20031,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20032=*
|
||||
entry_cfg_node(#20032,#20001)
|
||||
#20033=@"loc,{#10000},1,1,1,0"
|
||||
|
||||
@@ -133,6 +133,7 @@ scopes(#20046,3)
|
||||
scopenodes(#20001,#20046)
|
||||
scopenesting(#20046,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20047=*
|
||||
entry_cfg_node(#20047,#20001)
|
||||
#20048=@"loc,{#10000},1,1,1,0"
|
||||
|
||||
@@ -223,6 +223,7 @@ scopes(#20083,3)
|
||||
scopenodes(#20001,#20083)
|
||||
scopenesting(#20083,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20084=*
|
||||
stmts(#20084,30,#20001,0,"export ... om ""m"";")
|
||||
hasLocation(#20084,#20003)
|
||||
|
||||
@@ -75,6 +75,7 @@ scopes(#20025,3)
|
||||
scopenodes(#20001,#20025)
|
||||
scopenesting(#20025,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20026=*
|
||||
entry_cfg_node(#20026,#20001)
|
||||
#20027=@"loc,{#10000},1,1,1,0"
|
||||
|
||||
@@ -186,6 +186,7 @@ scopes(#20069,3)
|
||||
scopenodes(#20001,#20069)
|
||||
scopenesting(#20069,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20070=@"var;{type};{#20069}"
|
||||
variables(#20070,"type",#20069)
|
||||
#20071=@"local_type_name;{type};{#20069}"
|
||||
|
||||
@@ -210,6 +210,7 @@ scopes(#20072,3)
|
||||
scopenodes(#20001,#20072)
|
||||
scopenesting(#20072,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20073=*
|
||||
entry_cfg_node(#20073,#20001)
|
||||
#20074=@"loc,{#10000},1,1,1,0"
|
||||
|
||||
@@ -165,6 +165,7 @@ scopes(#20058,3)
|
||||
scopenodes(#20001,#20058)
|
||||
scopenesting(#20058,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20059=@"var;{Foo};{#20058}"
|
||||
variables(#20059,"Foo",#20058)
|
||||
#20060=@"local_type_name;{Foo};{#20058}"
|
||||
|
||||
@@ -104,6 +104,7 @@ scopes(#20035,3)
|
||||
scopenodes(#20001,#20035)
|
||||
scopenesting(#20035,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20036=@"var;{foo};{#20035}"
|
||||
variables(#20036,"foo",#20035)
|
||||
#20037=@"local_type_name;{foo};{#20035}"
|
||||
|
||||
@@ -175,6 +175,7 @@ scopes(#20053,3)
|
||||
scopenodes(#20037,#20053)
|
||||
scopenesting(#20053,#20000)
|
||||
isModule(#20037)
|
||||
isES2015Module(#20037)
|
||||
#20054=@"var;{inAModule};{#20053}"
|
||||
variables(#20054,"inAModule",#20053)
|
||||
#20055=*
|
||||
@@ -259,6 +260,7 @@ scopes(#20079,3)
|
||||
scopenodes(#20061,#20079)
|
||||
scopenesting(#20079,#20000)
|
||||
isModule(#20061)
|
||||
isES2015Module(#20061)
|
||||
#20080=@"var;{f};{#20079}"
|
||||
variables(#20080,"f",#20079)
|
||||
#20081=@"local_type_name;{f};{#20079}"
|
||||
|
||||
@@ -50,6 +50,7 @@ scopes(#20016,3)
|
||||
scopenodes(#20001,#20016)
|
||||
scopenesting(#20016,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20017=@"var;{x};{#20016}"
|
||||
variables(#20017,"x",#20016)
|
||||
#20018=*
|
||||
|
||||
@@ -310,6 +310,7 @@ scopes(#20112,3)
|
||||
scopenodes(#20001,#20112)
|
||||
scopenesting(#20112,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20113=@"var;{fun};{#20112}"
|
||||
variables(#20113,"fun",#20112)
|
||||
#20114=@"var;{Class};{#20112}"
|
||||
|
||||
@@ -154,6 +154,7 @@ scopes(#20055,3)
|
||||
scopenodes(#20001,#20055)
|
||||
scopenesting(#20055,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20056=@"var;{f};{#20055}"
|
||||
variables(#20056,"f",#20055)
|
||||
#20057=@"var;{foo};{#20055}"
|
||||
|
||||
@@ -50,6 +50,7 @@ scopes(#20015,3)
|
||||
scopenodes(#20001,#20015)
|
||||
scopenesting(#20015,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20016=*
|
||||
stmts(#20016,29,#20001,0,"export default 42;")
|
||||
hasLocation(#20016,#20003)
|
||||
|
||||
@@ -96,6 +96,7 @@ scopes(#20033,3)
|
||||
scopenodes(#20001,#20033)
|
||||
scopenesting(#20033,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20034=*
|
||||
stmts(#20034,30,#20001,0,"export ... foo();")
|
||||
hasLocation(#20034,#20003)
|
||||
|
||||
@@ -50,6 +50,7 @@ scopes(#20015,3)
|
||||
scopenodes(#20001,#20015)
|
||||
scopenesting(#20015,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20016=*
|
||||
stmts(#20016,33,#20001,0,"export = 42;")
|
||||
hasLocation(#20016,#20003)
|
||||
|
||||
@@ -117,6 +117,7 @@ scopes(#20041,3)
|
||||
scopenodes(#20001,#20041)
|
||||
scopenesting(#20041,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20042=@"var;{Something};{#20041}"
|
||||
variables(#20042,"Something",#20041)
|
||||
#20043=@"var;{importExport};{#20041}"
|
||||
|
||||
@@ -70,6 +70,7 @@ scopes(#20023,3)
|
||||
scopenodes(#20001,#20023)
|
||||
scopenesting(#20023,#20000)
|
||||
isModule(#20001)
|
||||
isES2015Module(#20001)
|
||||
#20024=@"var;{x};{#20023}"
|
||||
variables(#20024,"x",#20023)
|
||||
#20025=@"local_type_name;{x};{#20023}"
|
||||
|
||||
@@ -49,5 +49,7 @@ where
|
||||
// don't flag assignments in externs
|
||||
not dead.(ASTNode).inExternsFile() and
|
||||
// don't flag exported variables
|
||||
not any(ES2015Module m).exportsAs(v, _)
|
||||
not any(ES2015Module m).exportsAs(v, _) and
|
||||
// don't flag 'exports' assignments in closure modules
|
||||
not any(Closure::ClosureModule mod).getExportsVariable() = v
|
||||
select dead, "This definition of " + v.getName() + " is useless, since its value is never read."
|
||||
|
||||
@@ -46,5 +46,7 @@ where
|
||||
moduleExportsAssign(_, exportsVal) and
|
||||
// however, if there are no further uses of `exports` the assignment is useless anyway
|
||||
strictcount(exportsVar.getAnAccess()) > 1
|
||||
)
|
||||
) and
|
||||
// export assignments do work in closure modules
|
||||
not assgn.getTopLevel() instanceof Closure::ClosureModule
|
||||
select assgn, "Assigning to 'exports' does not export anything."
|
||||
|
||||
@@ -8,6 +8,7 @@ import semmle.javascript.AST
|
||||
import semmle.javascript.BasicBlocks
|
||||
import semmle.javascript.CFG
|
||||
import semmle.javascript.Classes
|
||||
import semmle.javascript.Closure
|
||||
import semmle.javascript.Comments
|
||||
import semmle.javascript.Concepts
|
||||
import semmle.javascript.Constants
|
||||
|
||||
@@ -1,75 +1,209 @@
|
||||
/**
|
||||
* Provides classes for working with Google Closure code.
|
||||
* Provides classes for working with the Closure-Library module system.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* A call to a function in the `goog` namespace such as `goog.provide` or `goog.load`.
|
||||
*/
|
||||
class GoogFunctionCall extends CallExpr {
|
||||
GoogFunctionCall() {
|
||||
exists(GlobalVariable gv | gv.getName() = "goog" |
|
||||
this.getCallee().(DotExpr).getBase() = gv.getAnAccess()
|
||||
module Closure {
|
||||
/**
|
||||
* A call to a function in the `goog` namespace such as `goog.provide` or `goog.load`.
|
||||
*/
|
||||
class GoogFunctionCall extends CallExpr {
|
||||
GoogFunctionCall() {
|
||||
exists(GlobalVariable gv | gv.getName() = "goog" |
|
||||
this.getCallee().(DotExpr).getBase() = gv.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the name of the invoked function. */
|
||||
string getFunctionName() { result = getCallee().(DotExpr).getPropertyName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression statement consisting of a call to a function
|
||||
* in the `goog` namespace.
|
||||
*/
|
||||
class GoogFunctionCallStmt extends ExprStmt {
|
||||
GoogFunctionCallStmt() { super.getExpr() instanceof GoogFunctionCall }
|
||||
|
||||
override GoogFunctionCall getExpr() { result = super.getExpr() }
|
||||
|
||||
/** Gets the name of the invoked function. */
|
||||
string getFunctionName() { result = getExpr().getFunctionName() }
|
||||
|
||||
/** Gets the `i`th argument to the invoked function. */
|
||||
Expr getArgument(int i) { result = getExpr().getArgument(i) }
|
||||
|
||||
/** Gets an argument to the invoked function. */
|
||||
Expr getAnArgument() { result = getArgument(_) }
|
||||
}
|
||||
|
||||
abstract private class GoogNamespaceRef extends ExprOrStmt { abstract string getNamespaceId(); }
|
||||
|
||||
/**
|
||||
* A call to `goog.provide`.
|
||||
*/
|
||||
class GoogProvide extends GoogFunctionCallStmt, GoogNamespaceRef {
|
||||
GoogProvide() { getFunctionName() = "provide" }
|
||||
|
||||
/** Gets the identifier of the namespace created by this call. */
|
||||
override string getNamespaceId() { result = getArgument(0).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `goog.require`.
|
||||
*/
|
||||
class GoogRequire extends GoogFunctionCall, GoogNamespaceRef {
|
||||
GoogRequire() { getFunctionName() = "require" }
|
||||
|
||||
/** Gets the identifier of the namespace imported by this call. */
|
||||
override string getNamespaceId() { result = getArgument(0).getStringValue() }
|
||||
}
|
||||
|
||||
private class GoogRequireImport extends GoogRequire, Import {
|
||||
/** Gets the module in which this import appears. */
|
||||
override Module getEnclosingModule() { result = getTopLevel() }
|
||||
|
||||
/** Gets the (unresolved) path that this import refers to. */
|
||||
override PathExpr getImportedPath() { result = getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `goog.module` or `goog.declareModuleId`.
|
||||
*/
|
||||
class GoogModuleDeclaration extends GoogFunctionCallStmt, GoogNamespaceRef {
|
||||
GoogModuleDeclaration() {
|
||||
getFunctionName() = "module" or
|
||||
getFunctionName() = "declareModuleId"
|
||||
}
|
||||
|
||||
/** Gets the identifier of the namespace imported by this call. */
|
||||
override string getNamespaceId() { result = getArgument(0).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A module using the Closure module system, declared using `goog.module()` or `goog.declareModuleId()`.
|
||||
*/
|
||||
class ClosureModule extends Module {
|
||||
ClosureModule() { getAChildStmt() instanceof GoogModuleDeclaration }
|
||||
|
||||
/**
|
||||
* Gets the call to `goog.module` or `goog.declareModuleId` in this module.
|
||||
*/
|
||||
GoogModuleDeclaration getModuleDeclaration() { result = getAChildStmt() }
|
||||
|
||||
/**
|
||||
* Gets the namespace of this module.
|
||||
*/
|
||||
string getNamespaceId() { result = getModuleDeclaration().getNamespaceId() }
|
||||
|
||||
override Module getAnImportedModule() {
|
||||
exists(GoogRequireImport imprt |
|
||||
imprt.getEnclosingModule() = this and
|
||||
result.(ClosureModule).getNamespaceId() = imprt.getNamespaceId()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the top-level `exports` variable in this module, if this module is defined by
|
||||
* a `good.module` call.
|
||||
*
|
||||
* This variable denotes the object exported from this module.
|
||||
*
|
||||
* Has no result for ES6 modules using `goog.declareModuleId`.
|
||||
*/
|
||||
Variable getExportsVariable() {
|
||||
getModuleDeclaration().getFunctionName() = "module" and
|
||||
result = getScope().getVariable("exports")
|
||||
}
|
||||
|
||||
override predicate exports(string name, ASTNode export) {
|
||||
exists(DataFlow::PropWrite write, Expr base |
|
||||
write.getAstNode() = export and
|
||||
write.writes(base.flow(), name, _) and
|
||||
(
|
||||
base = getExportsVariable().getAReference()
|
||||
or
|
||||
base = getExportsVariable().getAnAssignedExpr()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A global Closure script, that is, a toplevel that is executed in the global scope and
|
||||
* contains a toplevel call to `goog.provide` or `goog.require`.
|
||||
*/
|
||||
class ClosureScript extends TopLevel {
|
||||
ClosureScript() {
|
||||
not this instanceof ClosureModule and
|
||||
getAChildStmt() instanceof GoogProvide
|
||||
or
|
||||
getAChildStmt().(ExprStmt).getExpr() instanceof GoogRequire
|
||||
}
|
||||
|
||||
/** Gets the identifier of a namespace required by this module. */
|
||||
string getARequiredNamespace() {
|
||||
result = getAChildStmt().(ExprStmt).getExpr().(GoogRequire).getNamespaceId()
|
||||
}
|
||||
|
||||
/** Gets the identifer of a namespace provided by this module. */
|
||||
string getAProvidedNamespace() { result = getAChildStmt().(GoogProvide).getNamespaceId() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` is a closure namespace, including proper namespace prefixes.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate isLibraryNamespacePath(string name) {
|
||||
exists(string namespace | namespace = any(GoogNamespaceRef provide).getNamespaceId() |
|
||||
name = namespace.substring(0, namespace.indexOf("."))
|
||||
or
|
||||
name = namespace
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the name of the invoked function. */
|
||||
string getFunctionName() { result = getCallee().(DotExpr).getPropertyName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression statement consisting of a call to a function
|
||||
* in the `goog` namespace.
|
||||
*/
|
||||
class GoogFunctionCallStmt extends ExprStmt {
|
||||
GoogFunctionCallStmt() { super.getExpr() instanceof GoogFunctionCall }
|
||||
|
||||
override GoogFunctionCall getExpr() { result = super.getExpr() }
|
||||
|
||||
/** Gets the name of the invoked function. */
|
||||
string getFunctionName() { result = getExpr().getFunctionName() }
|
||||
|
||||
/** Gets the `i`th argument to the invoked function. */
|
||||
Expr getArgument(int i) { result = getExpr().getArgument(i) }
|
||||
|
||||
/** Gets an argument to the invoked function. */
|
||||
Expr getAnArgument() { result = getArgument(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `goog.provide`.
|
||||
*/
|
||||
class GoogProvide extends GoogFunctionCallStmt {
|
||||
GoogProvide() { getFunctionName() = "provide" }
|
||||
|
||||
/** Gets the identifier of the namespace created by this call. */
|
||||
string getNamespaceId() { result = getArgument(0).(ConstantString).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `goog.require`.
|
||||
*/
|
||||
class GoogRequire extends GoogFunctionCallStmt {
|
||||
GoogRequire() { getFunctionName() = "require" }
|
||||
|
||||
/** Gets the identifier of the namespace imported by this call. */
|
||||
string getNamespaceId() { result = getArgument(0).(ConstantString).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Closure module, that is, a toplevel that contains a call to `goog.provide` or
|
||||
* `goog.require`.
|
||||
*/
|
||||
class ClosureModule extends TopLevel {
|
||||
ClosureModule() {
|
||||
getAChildStmt() instanceof GoogProvide or
|
||||
getAChildStmt() instanceof GoogRequire
|
||||
/**
|
||||
* Gets the closure namespace path addressed by the given dataflow node, if any.
|
||||
*/
|
||||
string getLibraryAccessPath(DataFlow::SourceNode node) {
|
||||
isLibraryNamespacePath(result) and
|
||||
node = DataFlow::globalVarRef(result)
|
||||
or
|
||||
isLibraryNamespacePath(result) and
|
||||
exists(DataFlow::PropRead read | node = read |
|
||||
result = getLibraryAccessPath(read.getBase().getALocalSource()) + "." + read.getPropertyName()
|
||||
)
|
||||
or
|
||||
// Associate an access path with the immediate RHS of a store on a closure namespace.
|
||||
// This is to support patterns like:
|
||||
// foo.bar = { baz() {} }
|
||||
exists(DataFlow::PropWrite write |
|
||||
node = write.getRhs() and
|
||||
result = getWrittenLibraryAccessPath(write)
|
||||
)
|
||||
or
|
||||
result = node.asExpr().(GoogRequire).getNamespaceId()
|
||||
}
|
||||
|
||||
/** Gets the identifier of a namespace required by this module. */
|
||||
string getARequiredNamespace() { result = getAChildStmt().(GoogRequire).getNamespaceId() }
|
||||
/**
|
||||
* Gets the closure namespace path written to by the given property write, if any.
|
||||
*/
|
||||
string getWrittenLibraryAccessPath(DataFlow::PropWrite node) {
|
||||
result = getLibraryAccessPath(node.getBase().getALocalSource()) + "." + node.getPropertyName()
|
||||
}
|
||||
|
||||
/** Gets the identifer of a namespace provided by this module. */
|
||||
string getAProvidedNamespace() { result = getAChildStmt().(GoogProvide).getNamespaceId() }
|
||||
/**
|
||||
* Gets a dataflow node that refers to the given Closure module.
|
||||
*/
|
||||
DataFlow::SourceNode moduleImport(string moduleName) {
|
||||
getLibraryAccessPath(result) = moduleName
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a dataflow node that refers to the given member of a Closure module.
|
||||
*/
|
||||
DataFlow::SourceNode moduleMember(string moduleName, string memberName) {
|
||||
result = moduleImport(moduleName).getAPropertyRead(memberName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import javascript
|
||||
*/
|
||||
class ES2015Module extends Module {
|
||||
ES2015Module() {
|
||||
isModule(this) and
|
||||
not isNodejs(this)
|
||||
isES2015Module(this)
|
||||
}
|
||||
|
||||
override ModuleScope getScope() { result.getScopeElement() = this }
|
||||
|
||||
@@ -1039,7 +1039,7 @@ module DataFlow {
|
||||
or
|
||||
exists(GlobalVarAccess va |
|
||||
nd = valueNode(va.(VarUse)) and
|
||||
cause = "global"
|
||||
if Closure::isLibraryNamespacePath(va.getName()) then cause = "heap" else cause = "global"
|
||||
)
|
||||
or
|
||||
exists(Expr e | e = nd.asExpr() and cause = "call" |
|
||||
|
||||
@@ -332,3 +332,48 @@ private class AnalyzedExportAssign extends AnalyzedPropertyWrite, DataFlow::Valu
|
||||
source = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow analysis for assignments to the `exports` variable in a Closure module.
|
||||
*/
|
||||
private class AnalyzedClosureExportAssign extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
override AssignExpr astNode;
|
||||
|
||||
Closure::ClosureModule mod;
|
||||
|
||||
AnalyzedClosureExportAssign() { astNode.getLhs() = mod.getExportsVariable().getAReference() }
|
||||
|
||||
override predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
|
||||
baseVal = TAbstractModuleObject(astNode.getTopLevel()) and
|
||||
propName = "exports" and
|
||||
source = astNode.getRhs().flow()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read of a global access path exported by a Closure library.
|
||||
*
|
||||
* This adds a direct flow edge to the assigned value.
|
||||
*/
|
||||
private class AnalyzedClosureGlobalAccessPath extends AnalyzedNode, AnalyzedPropertyRead {
|
||||
string accessPath;
|
||||
|
||||
AnalyzedClosureGlobalAccessPath() { accessPath = Closure::getLibraryAccessPath(this) }
|
||||
|
||||
override AnalyzedNode localFlowPred() {
|
||||
exists(DataFlow::PropWrite write |
|
||||
Closure::getWrittenLibraryAccessPath(write) = accessPath and
|
||||
result = write.getRhs()
|
||||
)
|
||||
or
|
||||
result = AnalyzedNode.super.localFlowPred()
|
||||
}
|
||||
|
||||
override predicate reads(AbstractValue base, string propName) {
|
||||
exists(Closure::ClosureModule mod |
|
||||
mod.getNamespaceId() = accessPath and
|
||||
base = TAbstractModuleObject(mod) and
|
||||
propName = "exports"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@ case @toplevel.kind of
|
||||
|
||||
isModule (int tl: @toplevel ref);
|
||||
isNodejs (int tl: @toplevel ref);
|
||||
isES2015Module (int tl: @toplevel ref);
|
||||
isClosureModule (int tl: @toplevel ref);
|
||||
|
||||
// statements
|
||||
#keyset[parent, idx]
|
||||
|
||||
22
javascript/ql/test/library-tests/Closure/CallGraph.expected
Normal file
22
javascript/ql/test/library-tests/Closure/CallGraph.expected
Normal file
@@ -0,0 +1,22 @@
|
||||
| tests/importFromEs6.js:9:1:9:15 | es6Module.fun() | tests/es6Module.js:3:8:3:24 | function fun() {} | 0 |
|
||||
| tests/importFromEs6.js:10:1:10:18 | es6ModuleDefault() | tests/es6ModuleDefault.js:3:16:3:28 | function() {} | 0 |
|
||||
| tests/importFromEs6.js:12:1:12:16 | googModule.fun() | tests/googModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/importFromEs6.js:13:1:13:19 | googModuleDefault() | tests/googModuleDefault.js:3:11:3:27 | function fun() {} | 0 |
|
||||
| tests/requireFromEs6.js:12:1:12:18 | globalModule.fun() | tests/globalModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromEs6.js:13:1:13:21 | globalM ... fault() | tests/globalModuleDefault.js:3:23:3:39 | function fun() {} | 0 |
|
||||
| tests/requireFromEs6.js:15:1:15:15 | es6Module.fun() | tests/es6Module.js:3:8:3:24 | function fun() {} | 0 |
|
||||
| tests/requireFromEs6.js:16:1:16:18 | es6ModuleDefault() | tests/es6ModuleDefault.js:3:16:3:28 | function() {} | 0 |
|
||||
| tests/requireFromEs6.js:18:1:18:16 | googModule.fun() | tests/googModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromEs6.js:19:1:19:19 | googModuleDefault() | tests/googModuleDefault.js:3:11:3:27 | function fun() {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:10:1:10:18 | x.y.z.global.fun() | tests/globalModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:11:1:11:21 | x.y.z.g ... fault() | tests/globalModuleDefault.js:3:23:3:39 | function fun() {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:13:1:13:16 | x.y.z.goog.fun() | tests/googModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:14:1:14:19 | x.y.z.googdefault() | tests/googModuleDefault.js:3:11:3:27 | function fun() {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:16:1:16:15 | x.y.z.es6.fun() | tests/es6Module.js:3:8:3:24 | function fun() {} | 0 |
|
||||
| tests/requireFromGlobalModule.js:17:1:17:18 | x.y.z.es6default() | tests/es6ModuleDefault.js:3:16:3:28 | function() {} | 0 |
|
||||
| tests/requireFromGoogModule.js:12:1:12:18 | globalModule.fun() | tests/globalModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromGoogModule.js:13:1:13:21 | globalM ... fault() | tests/globalModuleDefault.js:3:23:3:39 | function fun() {} | 0 |
|
||||
| tests/requireFromGoogModule.js:15:1:15:15 | es6Module.fun() | tests/es6Module.js:3:8:3:24 | function fun() {} | 0 |
|
||||
| tests/requireFromGoogModule.js:16:1:16:18 | es6ModuleDefault() | tests/es6ModuleDefault.js:3:16:3:28 | function() {} | 0 |
|
||||
| tests/requireFromGoogModule.js:18:1:18:16 | googModule.fun() | tests/googModule.js:4:6:4:10 | () {} | 0 |
|
||||
| tests/requireFromGoogModule.js:19:1:19:19 | googModuleDefault() | tests/googModuleDefault.js:3:11:3:27 | function fun() {} | 0 |
|
||||
4
javascript/ql/test/library-tests/Closure/CallGraph.ql
Normal file
4
javascript/ql/test/library-tests/Closure/CallGraph.ql
Normal file
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from DataFlow::InvokeNode node, int imprecision
|
||||
select node, node.getACallee(imprecision), imprecision
|
||||
@@ -1,2 +0,0 @@
|
||||
| a.js:1:1:5:1 | <toplevel> |
|
||||
| b.js:1:1:3:21 | <toplevel> |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from ClosureModule cm
|
||||
select cm
|
||||
@@ -1 +0,0 @@
|
||||
| a.js:1:1:5:1 | <toplevel> | a |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from ClosureModule cm
|
||||
select cm, cm.getAProvidedNamespace()
|
||||
@@ -1 +0,0 @@
|
||||
| b.js:1:1:3:21 | <toplevel> | a |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from ClosureModule cm
|
||||
select cm, cm.getARequiredNamespace()
|
||||
@@ -1,3 +0,0 @@
|
||||
| a.js:1:1:1:17 | goog.provide('a') | provide |
|
||||
| b.js:1:1:1:17 | goog.require('a') | require |
|
||||
| c.js:2:1:2:14 | goog.leyness() | leyness |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from GoogFunctionCall gfc
|
||||
select gfc, gfc.getFunctionName()
|
||||
@@ -1 +0,0 @@
|
||||
| a.js:1:1:1:18 | goog.provide('a'); | a |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from GoogProvide gp
|
||||
select gp, gp.getNamespaceId()
|
||||
@@ -1 +0,0 @@
|
||||
| b.js:1:1:1:18 | goog.require('a'); | a |
|
||||
@@ -1,4 +0,0 @@
|
||||
import semmle.javascript.Closure
|
||||
|
||||
from GoogRequire gr
|
||||
select gr, gr.getNamespaceId()
|
||||
@@ -0,0 +1,4 @@
|
||||
| tests/es6Module.js:0:0:0:0 | tests/es6Module.js |
|
||||
| tests/es6ModuleDefault.js:0:0:0:0 | tests/es6ModuleDefault.js |
|
||||
| tests/importFromEs6.js:0:0:0:0 | tests/importFromEs6.js |
|
||||
| tests/requireFromEs6.js:0:0:0:0 | tests/requireFromEs6.js |
|
||||
5
javascript/ql/test/library-tests/Closure/StrictMode.ql
Normal file
5
javascript/ql/test/library-tests/Closure/StrictMode.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from TopLevel tl
|
||||
where tl.isStrict()
|
||||
select tl.getFile()
|
||||
@@ -1,5 +0,0 @@
|
||||
goog.provide('a');
|
||||
|
||||
a.foo = function() {
|
||||
return 42;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
goog.require('a');
|
||||
|
||||
console.log(a.foo());
|
||||
@@ -1,2 +0,0 @@
|
||||
// not a Closure module
|
||||
goog.leyness();
|
||||
@@ -0,0 +1,51 @@
|
||||
| x | tests/globalModule.js:3:1:3:1 | x |
|
||||
| x | tests/globalModuleDefault.js:3:1:3:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:10:1:10:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:11:1:11:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:13:1:13:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:14:1:14:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:16:1:16:1 | x |
|
||||
| x | tests/requireFromGlobalModule.js:17:1:17:1 | x |
|
||||
| x.y | tests/globalModule.js:3:1:3:3 | x.y |
|
||||
| x.y | tests/globalModuleDefault.js:3:1:3:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:10:1:10:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:11:1:11:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:13:1:13:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:14:1:14:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:16:1:16:3 | x.y |
|
||||
| x.y | tests/requireFromGlobalModule.js:17:1:17:3 | x.y |
|
||||
| x.y.z | tests/globalModule.js:3:1:3:5 | x.y.z |
|
||||
| x.y.z | tests/globalModuleDefault.js:3:1:3:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:10:1:10:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:11:1:11:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:13:1:13:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:14:1:14:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:16:1:16:5 | x.y.z |
|
||||
| x.y.z | tests/requireFromGlobalModule.js:17:1:17:5 | x.y.z |
|
||||
| x.y.z.es6 | tests/requireFromEs6.js:6:17:6:41 | goog.re ... z.es6') |
|
||||
| x.y.z.es6 | tests/requireFromGlobalModule.js:7:1:7:25 | goog.re ... z.es6') |
|
||||
| x.y.z.es6 | tests/requireFromGlobalModule.js:16:1:16:9 | x.y.z.es6 |
|
||||
| x.y.z.es6 | tests/requireFromGoogModule.js:6:17:6:41 | goog.re ... z.es6') |
|
||||
| x.y.z.es6default | tests/requireFromEs6.js:7:24:7:55 | goog.re ... fault') |
|
||||
| x.y.z.es6default | tests/requireFromGlobalModule.js:8:1:8:32 | goog.re ... fault') |
|
||||
| x.y.z.es6default | tests/requireFromGlobalModule.js:17:1:17:16 | x.y.z.es6default |
|
||||
| x.y.z.es6default | tests/requireFromGoogModule.js:7:24:7:55 | goog.re ... fault') |
|
||||
| x.y.z.global | tests/globalModule.js:3:16:5:1 | {\\n fun() {}\\n} |
|
||||
| x.y.z.global | tests/requireFromEs6.js:3:20:3:47 | goog.re ... lobal') |
|
||||
| x.y.z.global | tests/requireFromGlobalModule.js:1:1:1:28 | goog.re ... lobal') |
|
||||
| x.y.z.global | tests/requireFromGlobalModule.js:10:1:10:12 | x.y.z.global |
|
||||
| x.y.z.global | tests/requireFromGoogModule.js:3:20:3:47 | goog.re ... lobal') |
|
||||
| x.y.z.global.fun | tests/globalModule.js:4:6:4:10 | () {} |
|
||||
| x.y.z.globaldefault | tests/globalModuleDefault.js:3:23:3:39 | function fun() {} |
|
||||
| x.y.z.globaldefault | tests/requireFromEs6.js:4:27:4:61 | goog.re ... fault') |
|
||||
| x.y.z.globaldefault | tests/requireFromGlobalModule.js:2:1:2:35 | goog.re ... fault') |
|
||||
| x.y.z.globaldefault | tests/requireFromGlobalModule.js:11:1:11:19 | x.y.z.globaldefault |
|
||||
| x.y.z.globaldefault | tests/requireFromGoogModule.js:4:27:4:61 | goog.re ... fault') |
|
||||
| x.y.z.goog | tests/requireFromEs6.js:9:18:9:43 | goog.re ... .goog') |
|
||||
| x.y.z.goog | tests/requireFromGlobalModule.js:4:1:4:26 | goog.re ... .goog') |
|
||||
| x.y.z.goog | tests/requireFromGlobalModule.js:13:1:13:10 | x.y.z.goog |
|
||||
| x.y.z.goog | tests/requireFromGoogModule.js:9:18:9:43 | goog.re ... .goog') |
|
||||
| x.y.z.googdefault | tests/requireFromEs6.js:10:25:10:57 | goog.re ... fault') |
|
||||
| x.y.z.googdefault | tests/requireFromGlobalModule.js:5:1:5:33 | goog.re ... fault') |
|
||||
| x.y.z.googdefault | tests/requireFromGlobalModule.js:14:1:14:17 | x.y.z.googdefault |
|
||||
| x.y.z.googdefault | tests/requireFromGoogModule.js:10:25:10:57 | goog.re ... fault') |
|
||||
4
javascript/ql/test/library-tests/Closure/moduleImport.ql
Normal file
4
javascript/ql/test/library-tests/Closure/moduleImport.ql
Normal file
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from string name
|
||||
select name, Closure::moduleImport(name)
|
||||
@@ -0,0 +1,31 @@
|
||||
| x | y | tests/globalModule.js:3:1:3:3 | x.y |
|
||||
| x | y | tests/globalModuleDefault.js:3:1:3:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:10:1:10:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:11:1:11:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:13:1:13:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:14:1:14:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:16:1:16:3 | x.y |
|
||||
| x | y | tests/requireFromGlobalModule.js:17:1:17:3 | x.y |
|
||||
| x.y | z | tests/globalModule.js:3:1:3:5 | x.y.z |
|
||||
| x.y | z | tests/globalModuleDefault.js:3:1:3:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:10:1:10:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:11:1:11:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:13:1:13:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:14:1:14:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:16:1:16:5 | x.y.z |
|
||||
| x.y | z | tests/requireFromGlobalModule.js:17:1:17:5 | x.y.z |
|
||||
| x.y.z | es6 | tests/requireFromGlobalModule.js:16:1:16:9 | x.y.z.es6 |
|
||||
| x.y.z | es6default | tests/requireFromGlobalModule.js:17:1:17:16 | x.y.z.es6default |
|
||||
| x.y.z | global | tests/requireFromGlobalModule.js:10:1:10:12 | x.y.z.global |
|
||||
| x.y.z | globaldefault | tests/requireFromGlobalModule.js:11:1:11:19 | x.y.z.globaldefault |
|
||||
| x.y.z | goog | tests/requireFromGlobalModule.js:13:1:13:10 | x.y.z.goog |
|
||||
| x.y.z | googdefault | tests/requireFromGlobalModule.js:14:1:14:17 | x.y.z.googdefault |
|
||||
| x.y.z.es6 | fun | tests/requireFromEs6.js:15:1:15:13 | es6Module.fun |
|
||||
| x.y.z.es6 | fun | tests/requireFromGlobalModule.js:16:1:16:13 | x.y.z.es6.fun |
|
||||
| x.y.z.es6 | fun | tests/requireFromGoogModule.js:15:1:15:13 | es6Module.fun |
|
||||
| x.y.z.global | fun | tests/requireFromEs6.js:12:1:12:16 | globalModule.fun |
|
||||
| x.y.z.global | fun | tests/requireFromGlobalModule.js:10:1:10:16 | x.y.z.global.fun |
|
||||
| x.y.z.global | fun | tests/requireFromGoogModule.js:12:1:12:16 | globalModule.fun |
|
||||
| x.y.z.goog | fun | tests/requireFromEs6.js:18:1:18:14 | googModule.fun |
|
||||
| x.y.z.goog | fun | tests/requireFromGlobalModule.js:13:1:13:14 | x.y.z.goog.fun |
|
||||
| x.y.z.goog | fun | tests/requireFromGoogModule.js:18:1:18:14 | googModule.fun |
|
||||
4
javascript/ql/test/library-tests/Closure/moduleMember.ql
Normal file
4
javascript/ql/test/library-tests/Closure/moduleMember.ql
Normal file
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from string mod, string name
|
||||
select mod, name, Closure::moduleMember(mod, name)
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.declareModuleId('x.y.z.es6');
|
||||
|
||||
export function fun() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.declareModuleId('x.y.z.es6default');
|
||||
|
||||
export default function() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
goog.provide('x.y.z.global');
|
||||
|
||||
x.y.z.global = {
|
||||
fun() {}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.provide('x.y.z.globaldefault');
|
||||
|
||||
x.y.z.globaldefault = function fun() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
goog.module('x.y.z.goog');
|
||||
|
||||
exports = {
|
||||
fun() {}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.module('x.y.z.googdefault');
|
||||
|
||||
exports = function fun() {};
|
||||
@@ -0,0 +1,13 @@
|
||||
// ES6 imports can import files by name, as long as they are modules
|
||||
|
||||
import * as googModule from './googModule';
|
||||
import * as googModuleDefault from './googModuleDefault';
|
||||
|
||||
import * as es6Module from './es6Module';
|
||||
import * as es6ModuleDefault from './es6ModuleDefault';
|
||||
|
||||
es6Module.fun();
|
||||
es6ModuleDefault();
|
||||
|
||||
googModule.fun();
|
||||
googModuleDefault();
|
||||
@@ -0,0 +1,19 @@
|
||||
import * as dummy from 'dummy'; // treat as ES6 module
|
||||
|
||||
let globalModule = goog.require('x.y.z.global');
|
||||
let globalModuleDefault = goog.require('x.y.z.globaldefault');
|
||||
|
||||
let es6Module = goog.require('x.y.z.es6');
|
||||
let es6ModuleDefault = goog.require('x.y.z.es6default');
|
||||
|
||||
let googModule = goog.require('x.y.z.goog');
|
||||
let googModuleDefault = goog.require('x.y.z.googdefault');
|
||||
|
||||
globalModule.fun();
|
||||
globalModuleDefault();
|
||||
|
||||
es6Module.fun();
|
||||
es6ModuleDefault();
|
||||
|
||||
googModule.fun();
|
||||
googModuleDefault();
|
||||
@@ -0,0 +1,17 @@
|
||||
goog.require('x.y.z.global');
|
||||
goog.require('x.y.z.globaldefault');
|
||||
|
||||
goog.require('x.y.z.goog');
|
||||
goog.require('x.y.z.googdefault');
|
||||
|
||||
goog.require('x.y.z.es6');
|
||||
goog.require('x.y.z.es6default');
|
||||
|
||||
x.y.z.global.fun();
|
||||
x.y.z.globaldefault();
|
||||
|
||||
x.y.z.goog.fun();
|
||||
x.y.z.googdefault();
|
||||
|
||||
x.y.z.es6.fun();
|
||||
x.y.z.es6default();
|
||||
@@ -0,0 +1,19 @@
|
||||
goog.module('test.importer');
|
||||
|
||||
let globalModule = goog.require('x.y.z.global');
|
||||
let globalModuleDefault = goog.require('x.y.z.globaldefault');
|
||||
|
||||
let es6Module = goog.require('x.y.z.es6');
|
||||
let es6ModuleDefault = goog.require('x.y.z.es6default');
|
||||
|
||||
let googModule = goog.require('x.y.z.goog');
|
||||
let googModuleDefault = goog.require('x.y.z.googdefault');
|
||||
|
||||
globalModule.fun();
|
||||
globalModuleDefault();
|
||||
|
||||
es6Module.fun();
|
||||
es6ModuleDefault();
|
||||
|
||||
googModule.fun();
|
||||
googModuleDefault();
|
||||
@@ -0,0 +1,3 @@
|
||||
| a.js:5:31:5:31 | o |
|
||||
| exports.js:3:9:3:15 | exports |
|
||||
| tst.html:6:3:6:7 | alert |
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from VarAccess access
|
||||
where access.getVariable() instanceof GlobalVariable
|
||||
select access
|
||||
@@ -1 +1,2 @@
|
||||
| exports.js:1:8:1:17 | * as dummy |
|
||||
| m/c.js:1:8:1:13 | * as b |
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
| b.js:1:8:1:8 | f | b.js:1:8:1:8 | f |
|
||||
| d.js:1:10:1:21 | default as g | d.js:1:21:1:21 | g |
|
||||
| d.js:1:24:1:29 | x as y | d.js:1:29:1:29 | y |
|
||||
| exports.js:1:8:1:17 | * as dummy | exports.js:1:13:1:17 | dummy |
|
||||
| f.ts:1:8:1:8 | g | f.ts:1:8:1:8 | g |
|
||||
| g.ts:1:9:1:11 | foo | g.ts:1:9:1:11 | foo |
|
||||
| import-in-mjs.mjs:1:8:1:24 | exported_from_mjs | import-in-mjs.mjs:1:8:1:24 | exported_from_mjs |
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
| b.js:1:1:1:20 | import f from './a'; | b.js:1:15:1:19 | './a' | 1 |
|
||||
| d.js:1:1:1:43 | import ... './a'; | d.js:1:38:1:42 | './a' | 2 |
|
||||
| d.js:2:1:2:13 | import './b'; | d.js:2:8:2:12 | './b' | 0 |
|
||||
| exports.js:1:1:1:31 | import ... dummy'; | exports.js:1:24:1:30 | 'dummy' | 1 |
|
||||
| f.ts:1:1:1:19 | import g from './e' | f.ts:1:15:1:19 | './e' | 1 |
|
||||
| g.ts:1:1:1:23 | import ... m './f' | g.ts:1:19:1:23 | './f' | 1 |
|
||||
| import-in-mjs.mjs:1:1:1:46 | import ... n-mjs'; | import-in-mjs.mjs:1:31:1:45 | 'export-in-mjs' | 1 |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user