mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #19078 from asgerf/js/name-resolution
JS: QL-side type/name resolution for TypeScript and JSDoc
This commit is contained in:
@@ -426,7 +426,6 @@ public class ScopeManager {
|
||||
// cases where we turn on the 'declKind' flags
|
||||
@Override
|
||||
public Void visit(FunctionDeclaration nd, Void v) {
|
||||
if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
|
||||
// strict mode functions are block-scoped, non-strict mode ones aren't
|
||||
if (blockscope == isStrict) visit(nd.getId(), DeclKind.var);
|
||||
return null;
|
||||
@@ -434,7 +433,6 @@ public class ScopeManager {
|
||||
|
||||
@Override
|
||||
public Void visit(ClassDeclaration nd, Void c) {
|
||||
if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
|
||||
if (blockscope) visit(nd.getClassDef().getId(), DeclKind.varAndType);
|
||||
return null;
|
||||
}
|
||||
@@ -483,7 +481,6 @@ public class ScopeManager {
|
||||
|
||||
@Override
|
||||
public Void visit(VariableDeclaration nd, Void v) {
|
||||
if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
|
||||
// in block scoping mode, only process 'let'; in non-block scoping
|
||||
// mode, only process non-'let'
|
||||
if (blockscope == nd.isBlockScoped(ecmaVersion)) visit(nd.getDeclarations());
|
||||
@@ -518,8 +515,7 @@ public class ScopeManager {
|
||||
@Override
|
||||
public Void visit(NamespaceDeclaration nd, Void c) {
|
||||
if (blockscope) return null;
|
||||
boolean isAmbientOutsideDtsFile = nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile();
|
||||
boolean hasVariable = nd.isInstantiated() && !isAmbientOutsideDtsFile;
|
||||
boolean hasVariable = nd.isInstantiated();
|
||||
visit(nd.getName(), hasVariable ? DeclKind.varAndNamespace : DeclKind.namespace);
|
||||
return null;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,61 +50,64 @@ toplevels(#20001,0)
|
||||
#20016=@"loc,{#10000},1,1,2,0"
|
||||
locations_default(#20016,#10000,1,1,2,0)
|
||||
hasLocation(#20001,#20016)
|
||||
#20017=*
|
||||
stmts(#20017,26,#20001,0,"declare class C {}")
|
||||
hasLocation(#20017,#20003)
|
||||
stmt_containers(#20017,#20001)
|
||||
has_declare_keyword(#20017)
|
||||
#20018=*
|
||||
exprs(#20018,78,#20017,0,"C")
|
||||
hasLocation(#20018,#20009)
|
||||
enclosing_stmt(#20018,#20017)
|
||||
expr_containers(#20018,#20001)
|
||||
literals("C","C",#20018)
|
||||
#20019=@"var;{C};{#20000}"
|
||||
variables(#20019,"C",#20000)
|
||||
decl(#20018,#20019)
|
||||
#20017=@"var;{C};{#20000}"
|
||||
variables(#20017,"C",#20000)
|
||||
#20018=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20018,"C",#20000)
|
||||
#20019=*
|
||||
stmts(#20019,26,#20001,0,"declare class C {}")
|
||||
hasLocation(#20019,#20003)
|
||||
stmt_containers(#20019,#20001)
|
||||
has_declare_keyword(#20019)
|
||||
#20020=*
|
||||
scopes(#20020,10)
|
||||
scopenodes(#20017,#20020)
|
||||
scopenesting(#20020,#20000)
|
||||
exprs(#20020,78,#20019,0,"C")
|
||||
hasLocation(#20020,#20009)
|
||||
enclosing_stmt(#20020,#20019)
|
||||
expr_containers(#20020,#20001)
|
||||
literals("C","C",#20020)
|
||||
decl(#20020,#20017)
|
||||
typedecl(#20020,#20018)
|
||||
#20021=*
|
||||
properties(#20021,#20017,2,0,"constructor() {}")
|
||||
#20022=@"loc,{#10000},1,17,1,16"
|
||||
locations_default(#20022,#10000,1,17,1,16)
|
||||
hasLocation(#20021,#20022)
|
||||
#20023=*
|
||||
exprs(#20023,0,#20021,0,"constructor")
|
||||
hasLocation(#20023,#20022)
|
||||
enclosing_stmt(#20023,#20017)
|
||||
expr_containers(#20023,#20001)
|
||||
literals("constructor","constructor",#20023)
|
||||
scopes(#20021,10)
|
||||
scopenodes(#20019,#20021)
|
||||
scopenesting(#20021,#20000)
|
||||
#20022=*
|
||||
properties(#20022,#20019,2,0,"constructor() {}")
|
||||
#20023=@"loc,{#10000},1,17,1,16"
|
||||
locations_default(#20023,#10000,1,17,1,16)
|
||||
hasLocation(#20022,#20023)
|
||||
#20024=*
|
||||
exprs(#20024,9,#20021,1,"() {}")
|
||||
hasLocation(#20024,#20022)
|
||||
enclosing_stmt(#20024,#20017)
|
||||
exprs(#20024,0,#20022,0,"constructor")
|
||||
hasLocation(#20024,#20023)
|
||||
enclosing_stmt(#20024,#20019)
|
||||
expr_containers(#20024,#20001)
|
||||
literals("constructor","constructor",#20024)
|
||||
#20025=*
|
||||
scopes(#20025,1)
|
||||
scopenodes(#20024,#20025)
|
||||
scopenesting(#20025,#20020)
|
||||
#20026=@"var;{arguments};{#20025}"
|
||||
variables(#20026,"arguments",#20025)
|
||||
is_arguments_object(#20026)
|
||||
#20027=*
|
||||
stmts(#20027,1,#20024,-2,"{}")
|
||||
hasLocation(#20027,#20022)
|
||||
stmt_containers(#20027,#20024)
|
||||
is_method(#20021)
|
||||
exprs(#20025,9,#20022,1,"() {}")
|
||||
hasLocation(#20025,#20023)
|
||||
enclosing_stmt(#20025,#20019)
|
||||
expr_containers(#20025,#20001)
|
||||
#20026=*
|
||||
scopes(#20026,1)
|
||||
scopenodes(#20025,#20026)
|
||||
scopenesting(#20026,#20021)
|
||||
#20027=@"var;{arguments};{#20026}"
|
||||
variables(#20027,"arguments",#20026)
|
||||
is_arguments_object(#20027)
|
||||
#20028=*
|
||||
entry_cfg_node(#20028,#20001)
|
||||
#20029=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20029,#10000,1,1,1,0)
|
||||
hasLocation(#20028,#20029)
|
||||
#20030=*
|
||||
exit_cfg_node(#20030,#20001)
|
||||
hasLocation(#20030,#20015)
|
||||
successor(#20017,#20030)
|
||||
successor(#20028,#20017)
|
||||
stmts(#20028,1,#20025,-2,"{}")
|
||||
hasLocation(#20028,#20023)
|
||||
stmt_containers(#20028,#20025)
|
||||
is_method(#20022)
|
||||
#20029=*
|
||||
entry_cfg_node(#20029,#20001)
|
||||
#20030=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20030,#10000,1,1,1,0)
|
||||
hasLocation(#20029,#20030)
|
||||
#20031=*
|
||||
exit_cfg_node(#20031,#20001)
|
||||
hasLocation(#20031,#20015)
|
||||
successor(#20019,#20031)
|
||||
successor(#20029,#20019)
|
||||
numlines(#10000,1,1,0)
|
||||
filetype(#10000,"typescript")
|
||||
|
||||
@@ -584,62 +584,63 @@ toplevels(#20001,0)
|
||||
#20221=@"loc,{#10000},1,1,16,0"
|
||||
locations_default(#20221,#10000,1,1,16,0)
|
||||
hasLocation(#20001,#20221)
|
||||
#20222=@"var;{C};{#20000}"
|
||||
variables(#20222,"C",#20000)
|
||||
#20223=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20223,"C",#20000)
|
||||
#20224=*
|
||||
stmts(#20224,18,#20001,0,"declare var A : any;")
|
||||
hasLocation(#20224,#20003)
|
||||
stmt_containers(#20224,#20001)
|
||||
has_declare_keyword(#20224)
|
||||
#20225=*
|
||||
exprs(#20225,64,#20224,0,"A : any")
|
||||
#20226=@"loc,{#10000},1,13,1,19"
|
||||
locations_default(#20226,#10000,1,13,1,19)
|
||||
hasLocation(#20225,#20226)
|
||||
enclosing_stmt(#20225,#20224)
|
||||
expr_containers(#20225,#20001)
|
||||
#20222=@"var;{A};{#20000}"
|
||||
variables(#20222,"A",#20000)
|
||||
#20223=@"var;{B};{#20000}"
|
||||
variables(#20223,"B",#20000)
|
||||
#20224=@"var;{C};{#20000}"
|
||||
variables(#20224,"C",#20000)
|
||||
variables(#20224,"C",#20000)
|
||||
#20225=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20225,"C",#20000)
|
||||
#20226=*
|
||||
stmts(#20226,18,#20001,0,"declare var A : any;")
|
||||
hasLocation(#20226,#20003)
|
||||
stmt_containers(#20226,#20001)
|
||||
has_declare_keyword(#20226)
|
||||
#20227=*
|
||||
exprs(#20227,78,#20225,0,"A")
|
||||
hasLocation(#20227,#20037)
|
||||
enclosing_stmt(#20227,#20224)
|
||||
exprs(#20227,64,#20226,0,"A : any")
|
||||
#20228=@"loc,{#10000},1,13,1,19"
|
||||
locations_default(#20228,#10000,1,13,1,19)
|
||||
hasLocation(#20227,#20228)
|
||||
enclosing_stmt(#20227,#20226)
|
||||
expr_containers(#20227,#20001)
|
||||
literals("A","A",#20227)
|
||||
#20228=@"var;{A};{#20000}"
|
||||
variables(#20228,"A",#20000)
|
||||
decl(#20227,#20228)
|
||||
#20229=*
|
||||
typeexprs(#20229,2,#20225,2,"any")
|
||||
hasLocation(#20229,#20041)
|
||||
enclosing_stmt(#20229,#20224)
|
||||
exprs(#20229,78,#20227,0,"A")
|
||||
hasLocation(#20229,#20037)
|
||||
enclosing_stmt(#20229,#20226)
|
||||
expr_containers(#20229,#20001)
|
||||
literals("any","any",#20229)
|
||||
literals("A","A",#20229)
|
||||
decl(#20229,#20222)
|
||||
#20230=*
|
||||
stmts(#20230,18,#20001,1,"declare var B : any;")
|
||||
hasLocation(#20230,#20005)
|
||||
stmt_containers(#20230,#20001)
|
||||
has_declare_keyword(#20230)
|
||||
typeexprs(#20230,2,#20227,2,"any")
|
||||
hasLocation(#20230,#20041)
|
||||
enclosing_stmt(#20230,#20226)
|
||||
expr_containers(#20230,#20001)
|
||||
literals("any","any",#20230)
|
||||
#20231=*
|
||||
exprs(#20231,64,#20230,0,"B : any")
|
||||
#20232=@"loc,{#10000},2,13,2,19"
|
||||
locations_default(#20232,#10000,2,13,2,19)
|
||||
hasLocation(#20231,#20232)
|
||||
enclosing_stmt(#20231,#20230)
|
||||
expr_containers(#20231,#20001)
|
||||
#20233=*
|
||||
exprs(#20233,78,#20231,0,"B")
|
||||
hasLocation(#20233,#20049)
|
||||
enclosing_stmt(#20233,#20230)
|
||||
expr_containers(#20233,#20001)
|
||||
literals("B","B",#20233)
|
||||
#20234=@"var;{B};{#20000}"
|
||||
variables(#20234,"B",#20000)
|
||||
decl(#20233,#20234)
|
||||
stmts(#20231,18,#20001,1,"declare var B : any;")
|
||||
hasLocation(#20231,#20005)
|
||||
stmt_containers(#20231,#20001)
|
||||
has_declare_keyword(#20231)
|
||||
#20232=*
|
||||
exprs(#20232,64,#20231,0,"B : any")
|
||||
#20233=@"loc,{#10000},2,13,2,19"
|
||||
locations_default(#20233,#10000,2,13,2,19)
|
||||
hasLocation(#20232,#20233)
|
||||
enclosing_stmt(#20232,#20231)
|
||||
expr_containers(#20232,#20001)
|
||||
#20234=*
|
||||
exprs(#20234,78,#20232,0,"B")
|
||||
hasLocation(#20234,#20049)
|
||||
enclosing_stmt(#20234,#20231)
|
||||
expr_containers(#20234,#20001)
|
||||
literals("B","B",#20234)
|
||||
decl(#20234,#20223)
|
||||
#20235=*
|
||||
typeexprs(#20235,2,#20231,2,"any")
|
||||
typeexprs(#20235,2,#20232,2,"any")
|
||||
hasLocation(#20235,#20053)
|
||||
enclosing_stmt(#20235,#20230)
|
||||
enclosing_stmt(#20235,#20231)
|
||||
expr_containers(#20235,#20001)
|
||||
literals("any","any",#20235)
|
||||
#20236=*
|
||||
@@ -660,7 +661,7 @@ hasLocation(#20239,#20061)
|
||||
enclosing_stmt(#20239,#20236)
|
||||
expr_containers(#20239,#20001)
|
||||
literals("C","C",#20239)
|
||||
decl(#20239,#20222)
|
||||
decl(#20239,#20224)
|
||||
#20240=*
|
||||
typeexprs(#20240,2,#20237,2,"any")
|
||||
hasLocation(#20240,#20065)
|
||||
@@ -679,8 +680,8 @@ hasLocation(#20243,#20071)
|
||||
enclosing_stmt(#20243,#20241)
|
||||
expr_containers(#20243,#20001)
|
||||
literals("C","C",#20243)
|
||||
decl(#20243,#20222)
|
||||
typedecl(#20243,#20223)
|
||||
decl(#20243,#20224)
|
||||
typedecl(#20243,#20225)
|
||||
#20244=*
|
||||
scopes(#20244,10)
|
||||
scopenodes(#20241,#20244)
|
||||
@@ -769,7 +770,7 @@ exprs(#20266,79,#20265,0,"A")
|
||||
hasLocation(#20266,#20093)
|
||||
expr_containers(#20266,#20258)
|
||||
literals("A","A",#20266)
|
||||
bind(#20266,#20228)
|
||||
bind(#20266,#20222)
|
||||
#20267=*
|
||||
stmts(#20267,1,#20258,-2,"{}")
|
||||
#20268=@"loc,{#10000},7,12,7,13"
|
||||
@@ -825,7 +826,7 @@ exprs(#20281,79,#20279,0,"A")
|
||||
hasLocation(#20281,#20109)
|
||||
expr_containers(#20281,#20272)
|
||||
literals("A","A",#20281)
|
||||
bind(#20281,#20228)
|
||||
bind(#20281,#20222)
|
||||
#20282=*
|
||||
exprs(#20282,94,#20277,1,"@B")
|
||||
#20283=@"loc,{#10000},8,9,8,10"
|
||||
@@ -837,7 +838,7 @@ exprs(#20284,79,#20282,0,"B")
|
||||
hasLocation(#20284,#20113)
|
||||
expr_containers(#20284,#20272)
|
||||
literals("B","B",#20284)
|
||||
bind(#20284,#20234)
|
||||
bind(#20284,#20223)
|
||||
#20285=*
|
||||
stmts(#20285,1,#20272,-2,"{}")
|
||||
#20286=@"loc,{#10000},8,16,8,17"
|
||||
@@ -899,7 +900,7 @@ exprs(#20300,79,#20299,0,"A")
|
||||
hasLocation(#20300,#20133)
|
||||
expr_containers(#20300,#20290)
|
||||
literals("A","A",#20300)
|
||||
bind(#20300,#20228)
|
||||
bind(#20300,#20222)
|
||||
#20301=*
|
||||
stmts(#20301,1,#20290,-2,"{}")
|
||||
#20302=@"loc,{#10000},10,18,10,19"
|
||||
@@ -963,7 +964,7 @@ exprs(#20317,79,#20315,0,"A")
|
||||
hasLocation(#20317,#20153)
|
||||
expr_containers(#20317,#20306)
|
||||
literals("A","A",#20317)
|
||||
bind(#20317,#20228)
|
||||
bind(#20317,#20222)
|
||||
#20318=*
|
||||
exprs(#20318,94,#20313,1,"@B")
|
||||
#20319=@"loc,{#10000},11,15,11,16"
|
||||
@@ -975,7 +976,7 @@ exprs(#20320,79,#20318,0,"B")
|
||||
hasLocation(#20320,#20157)
|
||||
expr_containers(#20320,#20306)
|
||||
literals("B","B",#20320)
|
||||
bind(#20320,#20234)
|
||||
bind(#20320,#20223)
|
||||
#20321=*
|
||||
stmts(#20321,1,#20306,-2,"{}")
|
||||
#20322=@"loc,{#10000},11,22,11,23"
|
||||
@@ -1037,7 +1038,7 @@ exprs(#20336,79,#20335,0,"A")
|
||||
hasLocation(#20336,#20173)
|
||||
expr_containers(#20336,#20326)
|
||||
literals("A","A",#20336)
|
||||
bind(#20336,#20228)
|
||||
bind(#20336,#20222)
|
||||
#20337=*
|
||||
exprs(#20337,104,#20326,-12,"@B")
|
||||
#20338=@"loc,{#10000},13,12,13,13"
|
||||
@@ -1053,7 +1054,7 @@ exprs(#20340,79,#20339,0,"B")
|
||||
hasLocation(#20340,#20181)
|
||||
expr_containers(#20340,#20326)
|
||||
literals("B","B",#20340)
|
||||
bind(#20340,#20234)
|
||||
bind(#20340,#20223)
|
||||
#20341=*
|
||||
stmts(#20341,1,#20326,-2,"{}")
|
||||
#20342=@"loc,{#10000},13,18,13,19"
|
||||
@@ -1115,7 +1116,7 @@ exprs(#20356,79,#20355,0,"A")
|
||||
hasLocation(#20356,#20197)
|
||||
expr_containers(#20356,#20346)
|
||||
literals("A","A",#20356)
|
||||
bind(#20356,#20228)
|
||||
bind(#20356,#20222)
|
||||
#20357=*
|
||||
exprs(#20357,104,#20346,-12,"@B @C")
|
||||
#20358=@"loc,{#10000},14,12,14,16"
|
||||
@@ -1133,7 +1134,7 @@ exprs(#20361,79,#20359,0,"B")
|
||||
hasLocation(#20361,#20205)
|
||||
expr_containers(#20361,#20346)
|
||||
literals("B","B",#20361)
|
||||
bind(#20361,#20234)
|
||||
bind(#20361,#20223)
|
||||
#20362=*
|
||||
exprs(#20362,94,#20357,1,"@C")
|
||||
#20363=@"loc,{#10000},14,15,14,16"
|
||||
@@ -1145,7 +1146,7 @@ exprs(#20364,79,#20362,0,"C")
|
||||
hasLocation(#20364,#20209)
|
||||
expr_containers(#20364,#20346)
|
||||
literals("C","C",#20364)
|
||||
bind(#20364,#20222)
|
||||
bind(#20364,#20224)
|
||||
#20365=*
|
||||
stmts(#20365,1,#20346,-2,"{}")
|
||||
#20366=@"loc,{#10000},14,22,14,23"
|
||||
@@ -1349,8 +1350,8 @@ successor(#20265,#20263)
|
||||
successor(#20263,#20281)
|
||||
successor(#20241,#20266)
|
||||
successor(#20236,#20243)
|
||||
successor(#20230,#20236)
|
||||
successor(#20224,#20230)
|
||||
successor(#20374,#20224)
|
||||
successor(#20231,#20236)
|
||||
successor(#20226,#20231)
|
||||
successor(#20374,#20226)
|
||||
numlines(#10000,15,12,0)
|
||||
filetype(#10000,"typescript")
|
||||
|
||||
@@ -694,506 +694,509 @@ toplevels(#20001,0)
|
||||
#20252=@"loc,{#10000},2,1,30,0"
|
||||
locations_default(#20252,#10000,2,1,30,0)
|
||||
hasLocation(#20001,#20252)
|
||||
#20253=@"var;{C};{#20000}"
|
||||
variables(#20253,"C",#20000)
|
||||
#20254=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20254,"C",#20000)
|
||||
#20255=*
|
||||
stmts(#20255,17,#20001,0,"declare ... on f();")
|
||||
hasLocation(#20255,#20020)
|
||||
stmt_containers(#20255,#20001)
|
||||
has_declare_keyword(#20255)
|
||||
#20256=*
|
||||
exprs(#20256,78,#20255,-1,"f")
|
||||
hasLocation(#20256,#20079)
|
||||
expr_containers(#20256,#20255)
|
||||
literals("f","f",#20256)
|
||||
#20257=@"var;{f};{#20000}"
|
||||
variables(#20257,"f",#20000)
|
||||
decl(#20256,#20257)
|
||||
#20253=@"var;{f};{#20000}"
|
||||
variables(#20253,"f",#20000)
|
||||
#20254=@"var;{C};{#20000}"
|
||||
variables(#20254,"C",#20000)
|
||||
#20255=@"var;{D};{#20000}"
|
||||
variables(#20255,"D",#20000)
|
||||
#20256=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20256,"C",#20000)
|
||||
#20257=@"local_type_name;{D};{#20000}"
|
||||
local_type_names(#20257,"D",#20000)
|
||||
#20258=*
|
||||
scopes(#20258,1)
|
||||
scopenodes(#20255,#20258)
|
||||
scopenesting(#20258,#20000)
|
||||
#20259=@"var;{arguments};{#20258}"
|
||||
variables(#20259,"arguments",#20258)
|
||||
is_arguments_object(#20259)
|
||||
stmts(#20258,17,#20001,0,"declare ... on f();")
|
||||
hasLocation(#20258,#20020)
|
||||
stmt_containers(#20258,#20001)
|
||||
has_declare_keyword(#20258)
|
||||
#20259=*
|
||||
exprs(#20259,78,#20258,-1,"f")
|
||||
hasLocation(#20259,#20079)
|
||||
expr_containers(#20259,#20258)
|
||||
literals("f","f",#20259)
|
||||
decl(#20259,#20253)
|
||||
#20260=*
|
||||
stmts(#20260,26,#20001,1,"abstrac ... mber;\n}")
|
||||
#20261=@"loc,{#10000},4,1,15,1"
|
||||
locations_default(#20261,#10000,4,1,15,1)
|
||||
hasLocation(#20260,#20261)
|
||||
stmt_containers(#20260,#20001)
|
||||
is_abstract_class(#20260)
|
||||
scopes(#20260,1)
|
||||
scopenodes(#20258,#20260)
|
||||
scopenesting(#20260,#20000)
|
||||
#20261=@"var;{arguments};{#20260}"
|
||||
variables(#20261,"arguments",#20260)
|
||||
is_arguments_object(#20261)
|
||||
#20262=*
|
||||
exprs(#20262,78,#20260,0,"C")
|
||||
hasLocation(#20262,#20091)
|
||||
enclosing_stmt(#20262,#20260)
|
||||
expr_containers(#20262,#20001)
|
||||
literals("C","C",#20262)
|
||||
decl(#20262,#20253)
|
||||
typedecl(#20262,#20254)
|
||||
#20263=*
|
||||
scopes(#20263,10)
|
||||
scopenodes(#20260,#20263)
|
||||
scopenesting(#20263,#20000)
|
||||
stmts(#20262,26,#20001,1,"abstrac ... mber;\n}")
|
||||
#20263=@"loc,{#10000},4,1,15,1"
|
||||
locations_default(#20263,#10000,4,1,15,1)
|
||||
hasLocation(#20262,#20263)
|
||||
stmt_containers(#20262,#20001)
|
||||
is_abstract_class(#20262)
|
||||
#20264=*
|
||||
properties(#20264,#20260,2,0,"abstract h();")
|
||||
#20265=@"loc,{#10000},6,3,6,15"
|
||||
locations_default(#20265,#10000,6,3,6,15)
|
||||
hasLocation(#20264,#20265)
|
||||
exprs(#20264,78,#20262,0,"C")
|
||||
hasLocation(#20264,#20091)
|
||||
enclosing_stmt(#20264,#20262)
|
||||
expr_containers(#20264,#20001)
|
||||
literals("C","C",#20264)
|
||||
decl(#20264,#20254)
|
||||
typedecl(#20264,#20256)
|
||||
#20265=*
|
||||
scopes(#20265,10)
|
||||
scopenodes(#20262,#20265)
|
||||
scopenesting(#20265,#20000)
|
||||
#20266=*
|
||||
exprs(#20266,0,#20264,0,"h")
|
||||
hasLocation(#20266,#20097)
|
||||
enclosing_stmt(#20266,#20260)
|
||||
expr_containers(#20266,#20001)
|
||||
literals("h","h",#20266)
|
||||
#20267=*
|
||||
exprs(#20267,9,#20264,1,"abstract h();")
|
||||
hasLocation(#20267,#20265)
|
||||
enclosing_stmt(#20267,#20260)
|
||||
expr_containers(#20267,#20001)
|
||||
properties(#20266,#20262,2,0,"abstract h();")
|
||||
#20267=@"loc,{#10000},6,3,6,15"
|
||||
locations_default(#20267,#10000,6,3,6,15)
|
||||
hasLocation(#20266,#20267)
|
||||
#20268=*
|
||||
scopes(#20268,1)
|
||||
scopenodes(#20267,#20268)
|
||||
scopenesting(#20268,#20263)
|
||||
#20269=@"var;{arguments};{#20268}"
|
||||
variables(#20269,"arguments",#20268)
|
||||
is_arguments_object(#20269)
|
||||
is_method(#20264)
|
||||
is_abstract_member(#20264)
|
||||
exprs(#20268,0,#20266,0,"h")
|
||||
hasLocation(#20268,#20097)
|
||||
enclosing_stmt(#20268,#20262)
|
||||
expr_containers(#20268,#20001)
|
||||
literals("h","h",#20268)
|
||||
#20269=*
|
||||
exprs(#20269,9,#20266,1,"abstract h();")
|
||||
hasLocation(#20269,#20267)
|
||||
enclosing_stmt(#20269,#20262)
|
||||
expr_containers(#20269,#20001)
|
||||
#20270=*
|
||||
properties(#20270,#20260,3,0,"g(x: nu ... number;")
|
||||
#20271=@"loc,{#10000},9,3,9,23"
|
||||
locations_default(#20271,#10000,9,3,9,23)
|
||||
hasLocation(#20270,#20271)
|
||||
scopes(#20270,1)
|
||||
scopenodes(#20269,#20270)
|
||||
scopenesting(#20270,#20265)
|
||||
#20271=@"var;{arguments};{#20270}"
|
||||
variables(#20271,"arguments",#20270)
|
||||
is_arguments_object(#20271)
|
||||
is_method(#20266)
|
||||
is_abstract_member(#20266)
|
||||
#20272=*
|
||||
exprs(#20272,0,#20270,0,"g")
|
||||
hasLocation(#20272,#20105)
|
||||
enclosing_stmt(#20272,#20260)
|
||||
expr_containers(#20272,#20001)
|
||||
literals("g","g",#20272)
|
||||
#20273=*
|
||||
exprs(#20273,9,#20270,1,"g(x: nu ... number;")
|
||||
hasLocation(#20273,#20271)
|
||||
enclosing_stmt(#20273,#20260)
|
||||
expr_containers(#20273,#20001)
|
||||
properties(#20272,#20262,3,0,"g(x: nu ... number;")
|
||||
#20273=@"loc,{#10000},9,3,9,23"
|
||||
locations_default(#20273,#10000,9,3,9,23)
|
||||
hasLocation(#20272,#20273)
|
||||
#20274=*
|
||||
scopes(#20274,1)
|
||||
scopenodes(#20273,#20274)
|
||||
scopenesting(#20274,#20263)
|
||||
#20275=@"var;{x};{#20274}"
|
||||
variables(#20275,"x",#20274)
|
||||
exprs(#20274,0,#20272,0,"g")
|
||||
hasLocation(#20274,#20105)
|
||||
enclosing_stmt(#20274,#20262)
|
||||
expr_containers(#20274,#20001)
|
||||
literals("g","g",#20274)
|
||||
#20275=*
|
||||
exprs(#20275,9,#20272,1,"g(x: nu ... number;")
|
||||
hasLocation(#20275,#20273)
|
||||
enclosing_stmt(#20275,#20262)
|
||||
expr_containers(#20275,#20001)
|
||||
#20276=*
|
||||
exprs(#20276,78,#20273,0,"x")
|
||||
hasLocation(#20276,#20109)
|
||||
expr_containers(#20276,#20273)
|
||||
literals("x","x",#20276)
|
||||
decl(#20276,#20275)
|
||||
#20277=@"var;{arguments};{#20274}"
|
||||
variables(#20277,"arguments",#20274)
|
||||
is_arguments_object(#20277)
|
||||
scopes(#20276,1)
|
||||
scopenodes(#20275,#20276)
|
||||
scopenesting(#20276,#20265)
|
||||
#20277=@"var;{x};{#20276}"
|
||||
variables(#20277,"x",#20276)
|
||||
#20278=*
|
||||
typeexprs(#20278,2,#20273,-3,"number")
|
||||
hasLocation(#20278,#20119)
|
||||
expr_containers(#20278,#20273)
|
||||
literals("number","number",#20278)
|
||||
#20279=*
|
||||
typeexprs(#20279,2,#20273,-6,"number")
|
||||
hasLocation(#20279,#20113)
|
||||
expr_containers(#20279,#20273)
|
||||
literals("number","number",#20279)
|
||||
is_method(#20270)
|
||||
exprs(#20278,78,#20275,0,"x")
|
||||
hasLocation(#20278,#20109)
|
||||
expr_containers(#20278,#20275)
|
||||
literals("x","x",#20278)
|
||||
decl(#20278,#20277)
|
||||
#20279=@"var;{arguments};{#20276}"
|
||||
variables(#20279,"arguments",#20276)
|
||||
is_arguments_object(#20279)
|
||||
#20280=*
|
||||
properties(#20280,#20260,4,0,"g(x: st ... string;")
|
||||
#20281=@"loc,{#10000},10,3,10,23"
|
||||
locations_default(#20281,#10000,10,3,10,23)
|
||||
hasLocation(#20280,#20281)
|
||||
typeexprs(#20280,2,#20275,-3,"number")
|
||||
hasLocation(#20280,#20119)
|
||||
expr_containers(#20280,#20275)
|
||||
literals("number","number",#20280)
|
||||
#20281=*
|
||||
typeexprs(#20281,2,#20275,-6,"number")
|
||||
hasLocation(#20281,#20113)
|
||||
expr_containers(#20281,#20275)
|
||||
literals("number","number",#20281)
|
||||
is_method(#20272)
|
||||
#20282=*
|
||||
exprs(#20282,0,#20280,0,"g")
|
||||
hasLocation(#20282,#20123)
|
||||
enclosing_stmt(#20282,#20260)
|
||||
expr_containers(#20282,#20001)
|
||||
literals("g","g",#20282)
|
||||
#20283=*
|
||||
exprs(#20283,9,#20280,1,"g(x: st ... string;")
|
||||
hasLocation(#20283,#20281)
|
||||
enclosing_stmt(#20283,#20260)
|
||||
expr_containers(#20283,#20001)
|
||||
properties(#20282,#20262,4,0,"g(x: st ... string;")
|
||||
#20283=@"loc,{#10000},10,3,10,23"
|
||||
locations_default(#20283,#10000,10,3,10,23)
|
||||
hasLocation(#20282,#20283)
|
||||
#20284=*
|
||||
scopes(#20284,1)
|
||||
scopenodes(#20283,#20284)
|
||||
scopenesting(#20284,#20263)
|
||||
#20285=@"var;{x};{#20284}"
|
||||
variables(#20285,"x",#20284)
|
||||
exprs(#20284,0,#20282,0,"g")
|
||||
hasLocation(#20284,#20123)
|
||||
enclosing_stmt(#20284,#20262)
|
||||
expr_containers(#20284,#20001)
|
||||
literals("g","g",#20284)
|
||||
#20285=*
|
||||
exprs(#20285,9,#20282,1,"g(x: st ... string;")
|
||||
hasLocation(#20285,#20283)
|
||||
enclosing_stmt(#20285,#20262)
|
||||
expr_containers(#20285,#20001)
|
||||
#20286=*
|
||||
exprs(#20286,78,#20283,0,"x")
|
||||
hasLocation(#20286,#20127)
|
||||
expr_containers(#20286,#20283)
|
||||
literals("x","x",#20286)
|
||||
decl(#20286,#20285)
|
||||
#20287=@"var;{arguments};{#20284}"
|
||||
variables(#20287,"arguments",#20284)
|
||||
is_arguments_object(#20287)
|
||||
scopes(#20286,1)
|
||||
scopenodes(#20285,#20286)
|
||||
scopenesting(#20286,#20265)
|
||||
#20287=@"var;{x};{#20286}"
|
||||
variables(#20287,"x",#20286)
|
||||
#20288=*
|
||||
typeexprs(#20288,2,#20283,-3,"string")
|
||||
hasLocation(#20288,#20137)
|
||||
expr_containers(#20288,#20283)
|
||||
literals("string","string",#20288)
|
||||
#20289=*
|
||||
typeexprs(#20289,2,#20283,-6,"string")
|
||||
hasLocation(#20289,#20131)
|
||||
expr_containers(#20289,#20283)
|
||||
literals("string","string",#20289)
|
||||
is_method(#20280)
|
||||
exprs(#20288,78,#20285,0,"x")
|
||||
hasLocation(#20288,#20127)
|
||||
expr_containers(#20288,#20285)
|
||||
literals("x","x",#20288)
|
||||
decl(#20288,#20287)
|
||||
#20289=@"var;{arguments};{#20286}"
|
||||
variables(#20289,"arguments",#20286)
|
||||
is_arguments_object(#20289)
|
||||
#20290=*
|
||||
properties(#20290,#20260,5,0,"g(x: any) {}")
|
||||
#20291=@"loc,{#10000},11,3,11,14"
|
||||
locations_default(#20291,#10000,11,3,11,14)
|
||||
hasLocation(#20290,#20291)
|
||||
typeexprs(#20290,2,#20285,-3,"string")
|
||||
hasLocation(#20290,#20137)
|
||||
expr_containers(#20290,#20285)
|
||||
literals("string","string",#20290)
|
||||
#20291=*
|
||||
typeexprs(#20291,2,#20285,-6,"string")
|
||||
hasLocation(#20291,#20131)
|
||||
expr_containers(#20291,#20285)
|
||||
literals("string","string",#20291)
|
||||
is_method(#20282)
|
||||
#20292=*
|
||||
exprs(#20292,0,#20290,0,"g")
|
||||
hasLocation(#20292,#20141)
|
||||
enclosing_stmt(#20292,#20260)
|
||||
expr_containers(#20292,#20001)
|
||||
literals("g","g",#20292)
|
||||
#20293=*
|
||||
exprs(#20293,9,#20290,1,"g(x: any) {}")
|
||||
hasLocation(#20293,#20291)
|
||||
enclosing_stmt(#20293,#20260)
|
||||
expr_containers(#20293,#20001)
|
||||
properties(#20292,#20262,5,0,"g(x: any) {}")
|
||||
#20293=@"loc,{#10000},11,3,11,14"
|
||||
locations_default(#20293,#10000,11,3,11,14)
|
||||
hasLocation(#20292,#20293)
|
||||
#20294=*
|
||||
scopes(#20294,1)
|
||||
scopenodes(#20293,#20294)
|
||||
scopenesting(#20294,#20263)
|
||||
#20295=@"var;{x};{#20294}"
|
||||
variables(#20295,"x",#20294)
|
||||
exprs(#20294,0,#20292,0,"g")
|
||||
hasLocation(#20294,#20141)
|
||||
enclosing_stmt(#20294,#20262)
|
||||
expr_containers(#20294,#20001)
|
||||
literals("g","g",#20294)
|
||||
#20295=*
|
||||
exprs(#20295,9,#20292,1,"g(x: any) {}")
|
||||
hasLocation(#20295,#20293)
|
||||
enclosing_stmt(#20295,#20262)
|
||||
expr_containers(#20295,#20001)
|
||||
#20296=*
|
||||
exprs(#20296,78,#20293,0,"x")
|
||||
hasLocation(#20296,#20145)
|
||||
expr_containers(#20296,#20293)
|
||||
literals("x","x",#20296)
|
||||
decl(#20296,#20295)
|
||||
#20297=@"var;{arguments};{#20294}"
|
||||
variables(#20297,"arguments",#20294)
|
||||
is_arguments_object(#20297)
|
||||
scopes(#20296,1)
|
||||
scopenodes(#20295,#20296)
|
||||
scopenesting(#20296,#20265)
|
||||
#20297=@"var;{x};{#20296}"
|
||||
variables(#20297,"x",#20296)
|
||||
#20298=*
|
||||
typeexprs(#20298,2,#20293,-6,"any")
|
||||
hasLocation(#20298,#20149)
|
||||
expr_containers(#20298,#20293)
|
||||
literals("any","any",#20298)
|
||||
#20299=*
|
||||
stmts(#20299,1,#20293,-2,"{}")
|
||||
#20300=@"loc,{#10000},11,13,11,14"
|
||||
locations_default(#20300,#10000,11,13,11,14)
|
||||
hasLocation(#20299,#20300)
|
||||
stmt_containers(#20299,#20293)
|
||||
is_method(#20290)
|
||||
exprs(#20298,78,#20295,0,"x")
|
||||
hasLocation(#20298,#20145)
|
||||
expr_containers(#20298,#20295)
|
||||
literals("x","x",#20298)
|
||||
decl(#20298,#20297)
|
||||
#20299=@"var;{arguments};{#20296}"
|
||||
variables(#20299,"arguments",#20296)
|
||||
is_arguments_object(#20299)
|
||||
#20300=*
|
||||
typeexprs(#20300,2,#20295,-6,"any")
|
||||
hasLocation(#20300,#20149)
|
||||
expr_containers(#20300,#20295)
|
||||
literals("any","any",#20300)
|
||||
#20301=*
|
||||
properties(#20301,#20260,6,8,"abstract x: number;")
|
||||
#20302=@"loc,{#10000},14,3,14,21"
|
||||
locations_default(#20302,#10000,14,3,14,21)
|
||||
stmts(#20301,1,#20295,-2,"{}")
|
||||
#20302=@"loc,{#10000},11,13,11,14"
|
||||
locations_default(#20302,#10000,11,13,11,14)
|
||||
hasLocation(#20301,#20302)
|
||||
stmt_containers(#20301,#20295)
|
||||
is_method(#20292)
|
||||
#20303=*
|
||||
#20304=*
|
||||
exprs(#20304,0,#20301,0,"x")
|
||||
hasLocation(#20304,#20159)
|
||||
expr_containers(#20304,#20303)
|
||||
literals("x","x",#20304)
|
||||
is_abstract_member(#20301)
|
||||
properties(#20303,#20262,6,8,"abstract x: number;")
|
||||
#20304=@"loc,{#10000},14,3,14,21"
|
||||
locations_default(#20304,#10000,14,3,14,21)
|
||||
hasLocation(#20303,#20304)
|
||||
#20305=*
|
||||
typeexprs(#20305,2,#20301,2,"number")
|
||||
hasLocation(#20305,#20163)
|
||||
enclosing_stmt(#20305,#20260)
|
||||
expr_containers(#20305,#20001)
|
||||
literals("number","number",#20305)
|
||||
#20306=*
|
||||
properties(#20306,#20260,7,0,"constructor() {}")
|
||||
#20307=@"loc,{#10000},4,18,4,17"
|
||||
locations_default(#20307,#10000,4,18,4,17)
|
||||
hasLocation(#20306,#20307)
|
||||
exprs(#20306,0,#20303,0,"x")
|
||||
hasLocation(#20306,#20159)
|
||||
expr_containers(#20306,#20305)
|
||||
literals("x","x",#20306)
|
||||
is_abstract_member(#20303)
|
||||
#20307=*
|
||||
typeexprs(#20307,2,#20303,2,"number")
|
||||
hasLocation(#20307,#20163)
|
||||
enclosing_stmt(#20307,#20262)
|
||||
expr_containers(#20307,#20001)
|
||||
literals("number","number",#20307)
|
||||
#20308=*
|
||||
exprs(#20308,0,#20306,0,"constructor")
|
||||
hasLocation(#20308,#20307)
|
||||
enclosing_stmt(#20308,#20260)
|
||||
expr_containers(#20308,#20001)
|
||||
literals("constructor","constructor",#20308)
|
||||
exprs(#20303,9,#20306,1,"() {}")
|
||||
hasLocation(#20303,#20307)
|
||||
enclosing_stmt(#20303,#20260)
|
||||
expr_containers(#20303,#20001)
|
||||
#20309=*
|
||||
scopes(#20309,1)
|
||||
scopenodes(#20303,#20309)
|
||||
scopenesting(#20309,#20263)
|
||||
#20310=@"var;{arguments};{#20309}"
|
||||
variables(#20310,"arguments",#20309)
|
||||
is_arguments_object(#20310)
|
||||
properties(#20308,#20262,7,0,"constructor() {}")
|
||||
#20309=@"loc,{#10000},4,18,4,17"
|
||||
locations_default(#20309,#10000,4,18,4,17)
|
||||
hasLocation(#20308,#20309)
|
||||
#20310=*
|
||||
exprs(#20310,0,#20308,0,"constructor")
|
||||
hasLocation(#20310,#20309)
|
||||
enclosing_stmt(#20310,#20262)
|
||||
expr_containers(#20310,#20001)
|
||||
literals("constructor","constructor",#20310)
|
||||
exprs(#20305,9,#20308,1,"() {}")
|
||||
hasLocation(#20305,#20309)
|
||||
enclosing_stmt(#20305,#20262)
|
||||
expr_containers(#20305,#20001)
|
||||
#20311=*
|
||||
stmts(#20311,1,#20303,-2,"{}")
|
||||
hasLocation(#20311,#20307)
|
||||
stmt_containers(#20311,#20303)
|
||||
is_method(#20306)
|
||||
#20312=*
|
||||
stmts(#20312,26,#20001,2,"declare ... mber;\n}")
|
||||
#20313=@"loc,{#10000},18,1,29,1"
|
||||
locations_default(#20313,#10000,18,1,29,1)
|
||||
hasLocation(#20312,#20313)
|
||||
stmt_containers(#20312,#20001)
|
||||
has_declare_keyword(#20312)
|
||||
is_abstract_class(#20312)
|
||||
scopes(#20311,1)
|
||||
scopenodes(#20305,#20311)
|
||||
scopenesting(#20311,#20265)
|
||||
#20312=@"var;{arguments};{#20311}"
|
||||
variables(#20312,"arguments",#20311)
|
||||
is_arguments_object(#20312)
|
||||
#20313=*
|
||||
stmts(#20313,1,#20305,-2,"{}")
|
||||
hasLocation(#20313,#20309)
|
||||
stmt_containers(#20313,#20305)
|
||||
is_method(#20308)
|
||||
#20314=*
|
||||
exprs(#20314,78,#20312,0,"D")
|
||||
hasLocation(#20314,#20174)
|
||||
enclosing_stmt(#20314,#20312)
|
||||
expr_containers(#20314,#20001)
|
||||
literals("D","D",#20314)
|
||||
#20315=@"var;{D};{#20000}"
|
||||
variables(#20315,"D",#20000)
|
||||
decl(#20314,#20315)
|
||||
stmts(#20314,26,#20001,2,"declare ... mber;\n}")
|
||||
#20315=@"loc,{#10000},18,1,29,1"
|
||||
locations_default(#20315,#10000,18,1,29,1)
|
||||
hasLocation(#20314,#20315)
|
||||
stmt_containers(#20314,#20001)
|
||||
has_declare_keyword(#20314)
|
||||
is_abstract_class(#20314)
|
||||
#20316=*
|
||||
scopes(#20316,10)
|
||||
scopenodes(#20312,#20316)
|
||||
scopenesting(#20316,#20000)
|
||||
exprs(#20316,78,#20314,0,"D")
|
||||
hasLocation(#20316,#20174)
|
||||
enclosing_stmt(#20316,#20314)
|
||||
expr_containers(#20316,#20001)
|
||||
literals("D","D",#20316)
|
||||
decl(#20316,#20255)
|
||||
typedecl(#20316,#20257)
|
||||
#20317=*
|
||||
properties(#20317,#20312,2,0,"abstract h();")
|
||||
#20318=@"loc,{#10000},20,3,20,15"
|
||||
locations_default(#20318,#10000,20,3,20,15)
|
||||
hasLocation(#20317,#20318)
|
||||
#20319=*
|
||||
exprs(#20319,0,#20317,0,"h")
|
||||
hasLocation(#20319,#20180)
|
||||
enclosing_stmt(#20319,#20312)
|
||||
expr_containers(#20319,#20001)
|
||||
literals("h","h",#20319)
|
||||
scopes(#20317,10)
|
||||
scopenodes(#20314,#20317)
|
||||
scopenesting(#20317,#20000)
|
||||
#20318=*
|
||||
properties(#20318,#20314,2,0,"abstract h();")
|
||||
#20319=@"loc,{#10000},20,3,20,15"
|
||||
locations_default(#20319,#10000,20,3,20,15)
|
||||
hasLocation(#20318,#20319)
|
||||
#20320=*
|
||||
exprs(#20320,9,#20317,1,"abstract h();")
|
||||
hasLocation(#20320,#20318)
|
||||
enclosing_stmt(#20320,#20312)
|
||||
exprs(#20320,0,#20318,0,"h")
|
||||
hasLocation(#20320,#20180)
|
||||
enclosing_stmt(#20320,#20314)
|
||||
expr_containers(#20320,#20001)
|
||||
literals("h","h",#20320)
|
||||
#20321=*
|
||||
scopes(#20321,1)
|
||||
scopenodes(#20320,#20321)
|
||||
scopenesting(#20321,#20316)
|
||||
#20322=@"var;{arguments};{#20321}"
|
||||
variables(#20322,"arguments",#20321)
|
||||
is_arguments_object(#20322)
|
||||
is_method(#20317)
|
||||
is_abstract_member(#20317)
|
||||
#20323=*
|
||||
properties(#20323,#20312,3,0,"g(x: nu ... number;")
|
||||
#20324=@"loc,{#10000},23,3,23,23"
|
||||
locations_default(#20324,#10000,23,3,23,23)
|
||||
hasLocation(#20323,#20324)
|
||||
#20325=*
|
||||
exprs(#20325,0,#20323,0,"g")
|
||||
hasLocation(#20325,#20188)
|
||||
enclosing_stmt(#20325,#20312)
|
||||
expr_containers(#20325,#20001)
|
||||
literals("g","g",#20325)
|
||||
exprs(#20321,9,#20318,1,"abstract h();")
|
||||
hasLocation(#20321,#20319)
|
||||
enclosing_stmt(#20321,#20314)
|
||||
expr_containers(#20321,#20001)
|
||||
#20322=*
|
||||
scopes(#20322,1)
|
||||
scopenodes(#20321,#20322)
|
||||
scopenesting(#20322,#20317)
|
||||
#20323=@"var;{arguments};{#20322}"
|
||||
variables(#20323,"arguments",#20322)
|
||||
is_arguments_object(#20323)
|
||||
is_method(#20318)
|
||||
is_abstract_member(#20318)
|
||||
#20324=*
|
||||
properties(#20324,#20314,3,0,"g(x: nu ... number;")
|
||||
#20325=@"loc,{#10000},23,3,23,23"
|
||||
locations_default(#20325,#10000,23,3,23,23)
|
||||
hasLocation(#20324,#20325)
|
||||
#20326=*
|
||||
exprs(#20326,9,#20323,1,"g(x: nu ... number;")
|
||||
hasLocation(#20326,#20324)
|
||||
enclosing_stmt(#20326,#20312)
|
||||
exprs(#20326,0,#20324,0,"g")
|
||||
hasLocation(#20326,#20188)
|
||||
enclosing_stmt(#20326,#20314)
|
||||
expr_containers(#20326,#20001)
|
||||
literals("g","g",#20326)
|
||||
#20327=*
|
||||
scopes(#20327,1)
|
||||
scopenodes(#20326,#20327)
|
||||
scopenesting(#20327,#20316)
|
||||
#20328=@"var;{x};{#20327}"
|
||||
variables(#20328,"x",#20327)
|
||||
#20329=*
|
||||
exprs(#20329,78,#20326,0,"x")
|
||||
hasLocation(#20329,#20192)
|
||||
expr_containers(#20329,#20326)
|
||||
literals("x","x",#20329)
|
||||
decl(#20329,#20328)
|
||||
#20330=@"var;{arguments};{#20327}"
|
||||
variables(#20330,"arguments",#20327)
|
||||
is_arguments_object(#20330)
|
||||
#20331=*
|
||||
typeexprs(#20331,2,#20326,-3,"number")
|
||||
hasLocation(#20331,#20202)
|
||||
expr_containers(#20331,#20326)
|
||||
literals("number","number",#20331)
|
||||
exprs(#20327,9,#20324,1,"g(x: nu ... number;")
|
||||
hasLocation(#20327,#20325)
|
||||
enclosing_stmt(#20327,#20314)
|
||||
expr_containers(#20327,#20001)
|
||||
#20328=*
|
||||
scopes(#20328,1)
|
||||
scopenodes(#20327,#20328)
|
||||
scopenesting(#20328,#20317)
|
||||
#20329=@"var;{x};{#20328}"
|
||||
variables(#20329,"x",#20328)
|
||||
#20330=*
|
||||
exprs(#20330,78,#20327,0,"x")
|
||||
hasLocation(#20330,#20192)
|
||||
expr_containers(#20330,#20327)
|
||||
literals("x","x",#20330)
|
||||
decl(#20330,#20329)
|
||||
#20331=@"var;{arguments};{#20328}"
|
||||
variables(#20331,"arguments",#20328)
|
||||
is_arguments_object(#20331)
|
||||
#20332=*
|
||||
typeexprs(#20332,2,#20326,-6,"number")
|
||||
hasLocation(#20332,#20196)
|
||||
expr_containers(#20332,#20326)
|
||||
typeexprs(#20332,2,#20327,-3,"number")
|
||||
hasLocation(#20332,#20202)
|
||||
expr_containers(#20332,#20327)
|
||||
literals("number","number",#20332)
|
||||
is_method(#20323)
|
||||
#20333=*
|
||||
properties(#20333,#20312,4,0,"g(x: st ... string;")
|
||||
#20334=@"loc,{#10000},24,3,24,23"
|
||||
locations_default(#20334,#10000,24,3,24,23)
|
||||
hasLocation(#20333,#20334)
|
||||
#20335=*
|
||||
exprs(#20335,0,#20333,0,"g")
|
||||
hasLocation(#20335,#20206)
|
||||
enclosing_stmt(#20335,#20312)
|
||||
expr_containers(#20335,#20001)
|
||||
literals("g","g",#20335)
|
||||
typeexprs(#20333,2,#20327,-6,"number")
|
||||
hasLocation(#20333,#20196)
|
||||
expr_containers(#20333,#20327)
|
||||
literals("number","number",#20333)
|
||||
is_method(#20324)
|
||||
#20334=*
|
||||
properties(#20334,#20314,4,0,"g(x: st ... string;")
|
||||
#20335=@"loc,{#10000},24,3,24,23"
|
||||
locations_default(#20335,#10000,24,3,24,23)
|
||||
hasLocation(#20334,#20335)
|
||||
#20336=*
|
||||
exprs(#20336,9,#20333,1,"g(x: st ... string;")
|
||||
hasLocation(#20336,#20334)
|
||||
enclosing_stmt(#20336,#20312)
|
||||
exprs(#20336,0,#20334,0,"g")
|
||||
hasLocation(#20336,#20206)
|
||||
enclosing_stmt(#20336,#20314)
|
||||
expr_containers(#20336,#20001)
|
||||
literals("g","g",#20336)
|
||||
#20337=*
|
||||
scopes(#20337,1)
|
||||
scopenodes(#20336,#20337)
|
||||
scopenesting(#20337,#20316)
|
||||
#20338=@"var;{x};{#20337}"
|
||||
variables(#20338,"x",#20337)
|
||||
#20339=*
|
||||
exprs(#20339,78,#20336,0,"x")
|
||||
hasLocation(#20339,#20210)
|
||||
expr_containers(#20339,#20336)
|
||||
literals("x","x",#20339)
|
||||
decl(#20339,#20338)
|
||||
#20340=@"var;{arguments};{#20337}"
|
||||
variables(#20340,"arguments",#20337)
|
||||
is_arguments_object(#20340)
|
||||
#20341=*
|
||||
typeexprs(#20341,2,#20336,-3,"string")
|
||||
hasLocation(#20341,#20220)
|
||||
expr_containers(#20341,#20336)
|
||||
literals("string","string",#20341)
|
||||
exprs(#20337,9,#20334,1,"g(x: st ... string;")
|
||||
hasLocation(#20337,#20335)
|
||||
enclosing_stmt(#20337,#20314)
|
||||
expr_containers(#20337,#20001)
|
||||
#20338=*
|
||||
scopes(#20338,1)
|
||||
scopenodes(#20337,#20338)
|
||||
scopenesting(#20338,#20317)
|
||||
#20339=@"var;{x};{#20338}"
|
||||
variables(#20339,"x",#20338)
|
||||
#20340=*
|
||||
exprs(#20340,78,#20337,0,"x")
|
||||
hasLocation(#20340,#20210)
|
||||
expr_containers(#20340,#20337)
|
||||
literals("x","x",#20340)
|
||||
decl(#20340,#20339)
|
||||
#20341=@"var;{arguments};{#20338}"
|
||||
variables(#20341,"arguments",#20338)
|
||||
is_arguments_object(#20341)
|
||||
#20342=*
|
||||
typeexprs(#20342,2,#20336,-6,"string")
|
||||
hasLocation(#20342,#20214)
|
||||
expr_containers(#20342,#20336)
|
||||
typeexprs(#20342,2,#20337,-3,"string")
|
||||
hasLocation(#20342,#20220)
|
||||
expr_containers(#20342,#20337)
|
||||
literals("string","string",#20342)
|
||||
is_method(#20333)
|
||||
#20343=*
|
||||
properties(#20343,#20312,5,0,"g(x: any) {}")
|
||||
#20344=@"loc,{#10000},25,3,25,14"
|
||||
locations_default(#20344,#10000,25,3,25,14)
|
||||
hasLocation(#20343,#20344)
|
||||
#20345=*
|
||||
exprs(#20345,0,#20343,0,"g")
|
||||
hasLocation(#20345,#20224)
|
||||
enclosing_stmt(#20345,#20312)
|
||||
expr_containers(#20345,#20001)
|
||||
literals("g","g",#20345)
|
||||
typeexprs(#20343,2,#20337,-6,"string")
|
||||
hasLocation(#20343,#20214)
|
||||
expr_containers(#20343,#20337)
|
||||
literals("string","string",#20343)
|
||||
is_method(#20334)
|
||||
#20344=*
|
||||
properties(#20344,#20314,5,0,"g(x: any) {}")
|
||||
#20345=@"loc,{#10000},25,3,25,14"
|
||||
locations_default(#20345,#10000,25,3,25,14)
|
||||
hasLocation(#20344,#20345)
|
||||
#20346=*
|
||||
exprs(#20346,9,#20343,1,"g(x: any) {}")
|
||||
hasLocation(#20346,#20344)
|
||||
enclosing_stmt(#20346,#20312)
|
||||
exprs(#20346,0,#20344,0,"g")
|
||||
hasLocation(#20346,#20224)
|
||||
enclosing_stmt(#20346,#20314)
|
||||
expr_containers(#20346,#20001)
|
||||
literals("g","g",#20346)
|
||||
#20347=*
|
||||
scopes(#20347,1)
|
||||
scopenodes(#20346,#20347)
|
||||
scopenesting(#20347,#20316)
|
||||
#20348=@"var;{x};{#20347}"
|
||||
variables(#20348,"x",#20347)
|
||||
#20349=*
|
||||
exprs(#20349,78,#20346,0,"x")
|
||||
hasLocation(#20349,#20228)
|
||||
expr_containers(#20349,#20346)
|
||||
literals("x","x",#20349)
|
||||
decl(#20349,#20348)
|
||||
#20350=@"var;{arguments};{#20347}"
|
||||
variables(#20350,"arguments",#20347)
|
||||
is_arguments_object(#20350)
|
||||
#20351=*
|
||||
typeexprs(#20351,2,#20346,-6,"any")
|
||||
hasLocation(#20351,#20232)
|
||||
expr_containers(#20351,#20346)
|
||||
literals("any","any",#20351)
|
||||
exprs(#20347,9,#20344,1,"g(x: any) {}")
|
||||
hasLocation(#20347,#20345)
|
||||
enclosing_stmt(#20347,#20314)
|
||||
expr_containers(#20347,#20001)
|
||||
#20348=*
|
||||
scopes(#20348,1)
|
||||
scopenodes(#20347,#20348)
|
||||
scopenesting(#20348,#20317)
|
||||
#20349=@"var;{x};{#20348}"
|
||||
variables(#20349,"x",#20348)
|
||||
#20350=*
|
||||
exprs(#20350,78,#20347,0,"x")
|
||||
hasLocation(#20350,#20228)
|
||||
expr_containers(#20350,#20347)
|
||||
literals("x","x",#20350)
|
||||
decl(#20350,#20349)
|
||||
#20351=@"var;{arguments};{#20348}"
|
||||
variables(#20351,"arguments",#20348)
|
||||
is_arguments_object(#20351)
|
||||
#20352=*
|
||||
stmts(#20352,1,#20346,-2,"{}")
|
||||
#20353=@"loc,{#10000},25,13,25,14"
|
||||
locations_default(#20353,#10000,25,13,25,14)
|
||||
hasLocation(#20352,#20353)
|
||||
stmt_containers(#20352,#20346)
|
||||
is_method(#20343)
|
||||
#20354=*
|
||||
properties(#20354,#20312,6,8,"abstract x: number;")
|
||||
#20355=@"loc,{#10000},28,3,28,21"
|
||||
locations_default(#20355,#10000,28,3,28,21)
|
||||
hasLocation(#20354,#20355)
|
||||
#20356=*
|
||||
typeexprs(#20352,2,#20347,-6,"any")
|
||||
hasLocation(#20352,#20232)
|
||||
expr_containers(#20352,#20347)
|
||||
literals("any","any",#20352)
|
||||
#20353=*
|
||||
stmts(#20353,1,#20347,-2,"{}")
|
||||
#20354=@"loc,{#10000},25,13,25,14"
|
||||
locations_default(#20354,#10000,25,13,25,14)
|
||||
hasLocation(#20353,#20354)
|
||||
stmt_containers(#20353,#20347)
|
||||
is_method(#20344)
|
||||
#20355=*
|
||||
properties(#20355,#20314,6,8,"abstract x: number;")
|
||||
#20356=@"loc,{#10000},28,3,28,21"
|
||||
locations_default(#20356,#10000,28,3,28,21)
|
||||
hasLocation(#20355,#20356)
|
||||
#20357=*
|
||||
exprs(#20357,0,#20354,0,"x")
|
||||
hasLocation(#20357,#20242)
|
||||
expr_containers(#20357,#20356)
|
||||
literals("x","x",#20357)
|
||||
is_abstract_member(#20354)
|
||||
#20358=*
|
||||
typeexprs(#20358,2,#20354,2,"number")
|
||||
hasLocation(#20358,#20246)
|
||||
enclosing_stmt(#20358,#20312)
|
||||
expr_containers(#20358,#20001)
|
||||
literals("number","number",#20358)
|
||||
exprs(#20358,0,#20355,0,"x")
|
||||
hasLocation(#20358,#20242)
|
||||
expr_containers(#20358,#20357)
|
||||
literals("x","x",#20358)
|
||||
is_abstract_member(#20355)
|
||||
#20359=*
|
||||
properties(#20359,#20312,7,0,"constructor() {}")
|
||||
#20360=@"loc,{#10000},18,26,18,25"
|
||||
locations_default(#20360,#10000,18,26,18,25)
|
||||
hasLocation(#20359,#20360)
|
||||
#20361=*
|
||||
exprs(#20361,0,#20359,0,"constructor")
|
||||
hasLocation(#20361,#20360)
|
||||
enclosing_stmt(#20361,#20312)
|
||||
expr_containers(#20361,#20001)
|
||||
literals("constructor","constructor",#20361)
|
||||
exprs(#20356,9,#20359,1,"() {}")
|
||||
hasLocation(#20356,#20360)
|
||||
enclosing_stmt(#20356,#20312)
|
||||
expr_containers(#20356,#20001)
|
||||
typeexprs(#20359,2,#20355,2,"number")
|
||||
hasLocation(#20359,#20246)
|
||||
enclosing_stmt(#20359,#20314)
|
||||
expr_containers(#20359,#20001)
|
||||
literals("number","number",#20359)
|
||||
#20360=*
|
||||
properties(#20360,#20314,7,0,"constructor() {}")
|
||||
#20361=@"loc,{#10000},18,26,18,25"
|
||||
locations_default(#20361,#10000,18,26,18,25)
|
||||
hasLocation(#20360,#20361)
|
||||
#20362=*
|
||||
scopes(#20362,1)
|
||||
scopenodes(#20356,#20362)
|
||||
scopenesting(#20362,#20316)
|
||||
#20363=@"var;{arguments};{#20362}"
|
||||
variables(#20363,"arguments",#20362)
|
||||
is_arguments_object(#20363)
|
||||
#20364=*
|
||||
stmts(#20364,1,#20356,-2,"{}")
|
||||
hasLocation(#20364,#20360)
|
||||
stmt_containers(#20364,#20356)
|
||||
is_method(#20359)
|
||||
exprs(#20362,0,#20360,0,"constructor")
|
||||
hasLocation(#20362,#20361)
|
||||
enclosing_stmt(#20362,#20314)
|
||||
expr_containers(#20362,#20001)
|
||||
literals("constructor","constructor",#20362)
|
||||
exprs(#20357,9,#20360,1,"() {}")
|
||||
hasLocation(#20357,#20361)
|
||||
enclosing_stmt(#20357,#20314)
|
||||
expr_containers(#20357,#20001)
|
||||
#20363=*
|
||||
scopes(#20363,1)
|
||||
scopenodes(#20357,#20363)
|
||||
scopenesting(#20363,#20317)
|
||||
#20364=@"var;{arguments};{#20363}"
|
||||
variables(#20364,"arguments",#20363)
|
||||
is_arguments_object(#20364)
|
||||
#20365=*
|
||||
entry_cfg_node(#20365,#20001)
|
||||
#20366=@"loc,{#10000},2,1,2,0"
|
||||
locations_default(#20366,#10000,2,1,2,0)
|
||||
hasLocation(#20365,#20366)
|
||||
#20367=*
|
||||
exit_cfg_node(#20367,#20001)
|
||||
hasLocation(#20367,#20251)
|
||||
successor(#20312,#20367)
|
||||
successor(#20303,#20306)
|
||||
stmts(#20365,1,#20357,-2,"{}")
|
||||
hasLocation(#20365,#20361)
|
||||
stmt_containers(#20365,#20357)
|
||||
is_method(#20360)
|
||||
#20366=*
|
||||
entry_cfg_node(#20366,#20001)
|
||||
#20367=@"loc,{#10000},2,1,2,0"
|
||||
locations_default(#20367,#10000,2,1,2,0)
|
||||
hasLocation(#20366,#20367)
|
||||
#20368=*
|
||||
entry_cfg_node(#20368,#20303)
|
||||
hasLocation(#20368,#20307)
|
||||
exit_cfg_node(#20368,#20001)
|
||||
hasLocation(#20368,#20251)
|
||||
successor(#20314,#20368)
|
||||
successor(#20305,#20308)
|
||||
#20369=*
|
||||
exit_cfg_node(#20369,#20303)
|
||||
hasLocation(#20369,#20307)
|
||||
successor(#20311,#20369)
|
||||
successor(#20368,#20311)
|
||||
successor(#20308,#20303)
|
||||
successor(#20306,#20260)
|
||||
successor(#20293,#20290)
|
||||
entry_cfg_node(#20369,#20305)
|
||||
hasLocation(#20369,#20309)
|
||||
#20370=*
|
||||
entry_cfg_node(#20370,#20293)
|
||||
#20371=@"loc,{#10000},11,3,11,2"
|
||||
locations_default(#20371,#10000,11,3,11,2)
|
||||
hasLocation(#20370,#20371)
|
||||
#20372=*
|
||||
exit_cfg_node(#20372,#20293)
|
||||
#20373=@"loc,{#10000},11,15,11,14"
|
||||
locations_default(#20373,#10000,11,15,11,14)
|
||||
hasLocation(#20372,#20373)
|
||||
successor(#20299,#20372)
|
||||
successor(#20296,#20299)
|
||||
successor(#20370,#20296)
|
||||
successor(#20292,#20293)
|
||||
successor(#20290,#20308)
|
||||
successor(#20280,#20292)
|
||||
successor(#20270,#20280)
|
||||
successor(#20264,#20270)
|
||||
successor(#20262,#20264)
|
||||
successor(#20260,#20312)
|
||||
successor(#20255,#20262)
|
||||
successor(#20365,#20255)
|
||||
exit_cfg_node(#20370,#20305)
|
||||
hasLocation(#20370,#20309)
|
||||
successor(#20313,#20370)
|
||||
successor(#20369,#20313)
|
||||
successor(#20310,#20305)
|
||||
successor(#20308,#20262)
|
||||
successor(#20295,#20292)
|
||||
#20371=*
|
||||
entry_cfg_node(#20371,#20295)
|
||||
#20372=@"loc,{#10000},11,3,11,2"
|
||||
locations_default(#20372,#10000,11,3,11,2)
|
||||
hasLocation(#20371,#20372)
|
||||
#20373=*
|
||||
exit_cfg_node(#20373,#20295)
|
||||
#20374=@"loc,{#10000},11,15,11,14"
|
||||
locations_default(#20374,#10000,11,15,11,14)
|
||||
hasLocation(#20373,#20374)
|
||||
successor(#20301,#20373)
|
||||
successor(#20298,#20301)
|
||||
successor(#20371,#20298)
|
||||
successor(#20294,#20295)
|
||||
successor(#20292,#20310)
|
||||
successor(#20282,#20294)
|
||||
successor(#20272,#20282)
|
||||
successor(#20266,#20272)
|
||||
successor(#20264,#20266)
|
||||
successor(#20262,#20314)
|
||||
successor(#20258,#20264)
|
||||
successor(#20366,#20258)
|
||||
numlines(#10000,29,15,8)
|
||||
filetype(#10000,"typescript")
|
||||
|
||||
@@ -425,146 +425,146 @@ hasLocation(#20001,#20158)
|
||||
variables(#20159,"declaration",#20000)
|
||||
#20160=@"var;{f};{#20000}"
|
||||
variables(#20160,"f",#20000)
|
||||
#20161=@"var;{C};{#20000}"
|
||||
variables(#20161,"C",#20000)
|
||||
#20162=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20162,"C",#20000)
|
||||
#20163=@"local_type_name;{I};{#20000}"
|
||||
local_type_names(#20163,"I",#20000)
|
||||
#20164=*
|
||||
stmts(#20164,17,#20001,0,"functio ... ber) {}")
|
||||
hasLocation(#20164,#20003)
|
||||
stmt_containers(#20164,#20001)
|
||||
#20161=@"var;{ambient};{#20000}"
|
||||
variables(#20161,"ambient",#20000)
|
||||
#20162=@"var;{C};{#20000}"
|
||||
variables(#20162,"C",#20000)
|
||||
#20163=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20163,"C",#20000)
|
||||
#20164=@"local_type_name;{I};{#20000}"
|
||||
local_type_names(#20164,"I",#20000)
|
||||
#20165=*
|
||||
exprs(#20165,78,#20164,-1,"declaration")
|
||||
hasLocation(#20165,#20033)
|
||||
expr_containers(#20165,#20164)
|
||||
literals("declaration","declaration",#20165)
|
||||
decl(#20165,#20159)
|
||||
stmts(#20165,17,#20001,0,"functio ... ber) {}")
|
||||
hasLocation(#20165,#20003)
|
||||
stmt_containers(#20165,#20001)
|
||||
#20166=*
|
||||
scopes(#20166,1)
|
||||
scopenodes(#20164,#20166)
|
||||
scopenesting(#20166,#20000)
|
||||
#20167=@"var;{x};{#20166}"
|
||||
variables(#20167,"x",#20166)
|
||||
#20168=*
|
||||
exprs(#20168,78,#20164,0,"x")
|
||||
hasLocation(#20168,#20045)
|
||||
expr_containers(#20168,#20164)
|
||||
literals("x","x",#20168)
|
||||
decl(#20168,#20167)
|
||||
#20169=@"var;{arguments};{#20166}"
|
||||
variables(#20169,"arguments",#20166)
|
||||
is_arguments_object(#20169)
|
||||
#20170=*
|
||||
typeexprs(#20170,2,#20164,-4,"void")
|
||||
hasLocation(#20170,#20041)
|
||||
expr_containers(#20170,#20164)
|
||||
literals("void","void",#20170)
|
||||
exprs(#20166,78,#20165,-1,"declaration")
|
||||
hasLocation(#20166,#20033)
|
||||
expr_containers(#20166,#20165)
|
||||
literals("declaration","declaration",#20166)
|
||||
decl(#20166,#20159)
|
||||
#20167=*
|
||||
scopes(#20167,1)
|
||||
scopenodes(#20165,#20167)
|
||||
scopenesting(#20167,#20000)
|
||||
#20168=@"var;{x};{#20167}"
|
||||
variables(#20168,"x",#20167)
|
||||
#20169=*
|
||||
exprs(#20169,78,#20165,0,"x")
|
||||
hasLocation(#20169,#20045)
|
||||
expr_containers(#20169,#20165)
|
||||
literals("x","x",#20169)
|
||||
decl(#20169,#20168)
|
||||
#20170=@"var;{arguments};{#20167}"
|
||||
variables(#20170,"arguments",#20167)
|
||||
is_arguments_object(#20170)
|
||||
#20171=*
|
||||
typeexprs(#20171,2,#20164,-6,"number")
|
||||
hasLocation(#20171,#20049)
|
||||
expr_containers(#20171,#20164)
|
||||
literals("number","number",#20171)
|
||||
typeexprs(#20171,2,#20165,-4,"void")
|
||||
hasLocation(#20171,#20041)
|
||||
expr_containers(#20171,#20165)
|
||||
literals("void","void",#20171)
|
||||
#20172=*
|
||||
stmts(#20172,1,#20164,-2,"{}")
|
||||
#20173=@"loc,{#10000},1,45,1,46"
|
||||
locations_default(#20173,#10000,1,45,1,46)
|
||||
hasLocation(#20172,#20173)
|
||||
stmt_containers(#20172,#20164)
|
||||
#20174=*
|
||||
stmts(#20174,18,#20001,1,"var f = ... ber) {}")
|
||||
hasLocation(#20174,#20007)
|
||||
stmt_containers(#20174,#20001)
|
||||
typeexprs(#20172,2,#20165,-6,"number")
|
||||
hasLocation(#20172,#20049)
|
||||
expr_containers(#20172,#20165)
|
||||
literals("number","number",#20172)
|
||||
#20173=*
|
||||
stmts(#20173,1,#20165,-2,"{}")
|
||||
#20174=@"loc,{#10000},1,45,1,46"
|
||||
locations_default(#20174,#10000,1,45,1,46)
|
||||
hasLocation(#20173,#20174)
|
||||
stmt_containers(#20173,#20165)
|
||||
#20175=*
|
||||
exprs(#20175,64,#20174,0,"f = fun ... ber) {}")
|
||||
#20176=@"loc,{#10000},3,5,3,44"
|
||||
locations_default(#20176,#10000,3,5,3,44)
|
||||
hasLocation(#20175,#20176)
|
||||
enclosing_stmt(#20175,#20174)
|
||||
expr_containers(#20175,#20001)
|
||||
#20177=*
|
||||
exprs(#20177,78,#20175,0,"f")
|
||||
hasLocation(#20177,#20059)
|
||||
enclosing_stmt(#20177,#20174)
|
||||
expr_containers(#20177,#20001)
|
||||
literals("f","f",#20177)
|
||||
decl(#20177,#20160)
|
||||
stmts(#20175,18,#20001,1,"var f = ... ber) {}")
|
||||
hasLocation(#20175,#20007)
|
||||
stmt_containers(#20175,#20001)
|
||||
#20176=*
|
||||
exprs(#20176,64,#20175,0,"f = fun ... ber) {}")
|
||||
#20177=@"loc,{#10000},3,5,3,44"
|
||||
locations_default(#20177,#10000,3,5,3,44)
|
||||
hasLocation(#20176,#20177)
|
||||
enclosing_stmt(#20176,#20175)
|
||||
expr_containers(#20176,#20001)
|
||||
#20178=*
|
||||
exprs(#20178,9,#20175,1,"functio ... ber) {}")
|
||||
#20179=@"loc,{#10000},3,9,3,44"
|
||||
locations_default(#20179,#10000,3,9,3,44)
|
||||
hasLocation(#20178,#20179)
|
||||
enclosing_stmt(#20178,#20174)
|
||||
exprs(#20178,78,#20176,0,"f")
|
||||
hasLocation(#20178,#20059)
|
||||
enclosing_stmt(#20178,#20175)
|
||||
expr_containers(#20178,#20001)
|
||||
#20180=*
|
||||
scopes(#20180,1)
|
||||
scopenodes(#20178,#20180)
|
||||
scopenesting(#20180,#20000)
|
||||
#20181=@"var;{x};{#20180}"
|
||||
variables(#20181,"x",#20180)
|
||||
#20182=*
|
||||
exprs(#20182,78,#20178,0,"x")
|
||||
hasLocation(#20182,#20075)
|
||||
expr_containers(#20182,#20178)
|
||||
literals("x","x",#20182)
|
||||
decl(#20182,#20181)
|
||||
#20183=@"var;{arguments};{#20180}"
|
||||
variables(#20183,"arguments",#20180)
|
||||
is_arguments_object(#20183)
|
||||
#20184=*
|
||||
typeexprs(#20184,2,#20178,-4,"string")
|
||||
hasLocation(#20184,#20071)
|
||||
expr_containers(#20184,#20178)
|
||||
literals("string","string",#20184)
|
||||
literals("f","f",#20178)
|
||||
decl(#20178,#20160)
|
||||
#20179=*
|
||||
exprs(#20179,9,#20176,1,"functio ... ber) {}")
|
||||
#20180=@"loc,{#10000},3,9,3,44"
|
||||
locations_default(#20180,#10000,3,9,3,44)
|
||||
hasLocation(#20179,#20180)
|
||||
enclosing_stmt(#20179,#20175)
|
||||
expr_containers(#20179,#20001)
|
||||
#20181=*
|
||||
scopes(#20181,1)
|
||||
scopenodes(#20179,#20181)
|
||||
scopenesting(#20181,#20000)
|
||||
#20182=@"var;{x};{#20181}"
|
||||
variables(#20182,"x",#20181)
|
||||
#20183=*
|
||||
exprs(#20183,78,#20179,0,"x")
|
||||
hasLocation(#20183,#20075)
|
||||
expr_containers(#20183,#20179)
|
||||
literals("x","x",#20183)
|
||||
decl(#20183,#20182)
|
||||
#20184=@"var;{arguments};{#20181}"
|
||||
variables(#20184,"arguments",#20181)
|
||||
is_arguments_object(#20184)
|
||||
#20185=*
|
||||
typeexprs(#20185,2,#20178,-6,"number")
|
||||
hasLocation(#20185,#20079)
|
||||
expr_containers(#20185,#20178)
|
||||
literals("number","number",#20185)
|
||||
typeexprs(#20185,2,#20179,-4,"string")
|
||||
hasLocation(#20185,#20071)
|
||||
expr_containers(#20185,#20179)
|
||||
literals("string","string",#20185)
|
||||
#20186=*
|
||||
stmts(#20186,1,#20178,-2,"{}")
|
||||
#20187=@"loc,{#10000},3,43,3,44"
|
||||
locations_default(#20187,#10000,3,43,3,44)
|
||||
hasLocation(#20186,#20187)
|
||||
stmt_containers(#20186,#20178)
|
||||
#20188=*
|
||||
stmts(#20188,17,#20001,2,"declare ... umber);")
|
||||
hasLocation(#20188,#20011)
|
||||
stmt_containers(#20188,#20001)
|
||||
has_declare_keyword(#20188)
|
||||
typeexprs(#20186,2,#20179,-6,"number")
|
||||
hasLocation(#20186,#20079)
|
||||
expr_containers(#20186,#20179)
|
||||
literals("number","number",#20186)
|
||||
#20187=*
|
||||
stmts(#20187,1,#20179,-2,"{}")
|
||||
#20188=@"loc,{#10000},3,43,3,44"
|
||||
locations_default(#20188,#10000,3,43,3,44)
|
||||
hasLocation(#20187,#20188)
|
||||
stmt_containers(#20187,#20179)
|
||||
#20189=*
|
||||
exprs(#20189,78,#20188,-1,"ambient")
|
||||
hasLocation(#20189,#20091)
|
||||
expr_containers(#20189,#20188)
|
||||
literals("ambient","ambient",#20189)
|
||||
#20190=@"var;{ambient};{#20000}"
|
||||
variables(#20190,"ambient",#20000)
|
||||
decl(#20189,#20190)
|
||||
stmts(#20189,17,#20001,2,"declare ... umber);")
|
||||
hasLocation(#20189,#20011)
|
||||
stmt_containers(#20189,#20001)
|
||||
has_declare_keyword(#20189)
|
||||
#20190=*
|
||||
exprs(#20190,78,#20189,-1,"ambient")
|
||||
hasLocation(#20190,#20091)
|
||||
expr_containers(#20190,#20189)
|
||||
literals("ambient","ambient",#20190)
|
||||
decl(#20190,#20161)
|
||||
#20191=*
|
||||
scopes(#20191,1)
|
||||
scopenodes(#20188,#20191)
|
||||
scopenodes(#20189,#20191)
|
||||
scopenesting(#20191,#20000)
|
||||
#20192=@"var;{x};{#20191}"
|
||||
variables(#20192,"x",#20191)
|
||||
#20193=*
|
||||
exprs(#20193,78,#20188,0,"x")
|
||||
exprs(#20193,78,#20189,0,"x")
|
||||
hasLocation(#20193,#20103)
|
||||
expr_containers(#20193,#20188)
|
||||
expr_containers(#20193,#20189)
|
||||
literals("x","x",#20193)
|
||||
decl(#20193,#20192)
|
||||
#20194=@"var;{arguments};{#20191}"
|
||||
variables(#20194,"arguments",#20191)
|
||||
is_arguments_object(#20194)
|
||||
#20195=*
|
||||
typeexprs(#20195,2,#20188,-4,"string")
|
||||
typeexprs(#20195,2,#20189,-4,"string")
|
||||
hasLocation(#20195,#20099)
|
||||
expr_containers(#20195,#20188)
|
||||
expr_containers(#20195,#20189)
|
||||
literals("string","string",#20195)
|
||||
#20196=*
|
||||
typeexprs(#20196,2,#20188,-6,"number")
|
||||
typeexprs(#20196,2,#20189,-6,"number")
|
||||
hasLocation(#20196,#20107)
|
||||
expr_containers(#20196,#20188)
|
||||
expr_containers(#20196,#20189)
|
||||
literals("number","number",#20196)
|
||||
#20197=*
|
||||
stmts(#20197,26,#20001,3,"class C ... C) {}\n}")
|
||||
@@ -578,8 +578,8 @@ hasLocation(#20199,#20115)
|
||||
enclosing_stmt(#20199,#20197)
|
||||
expr_containers(#20199,#20001)
|
||||
literals("C","C",#20199)
|
||||
decl(#20199,#20161)
|
||||
typedecl(#20199,#20162)
|
||||
decl(#20199,#20162)
|
||||
typedecl(#20199,#20163)
|
||||
#20200=*
|
||||
scopes(#20200,10)
|
||||
scopenodes(#20197,#20200)
|
||||
@@ -612,7 +612,7 @@ typeexprs(#20207,0,#20204,-4,"C")
|
||||
hasLocation(#20207,#20127)
|
||||
expr_containers(#20207,#20204)
|
||||
literals("C","C",#20207)
|
||||
typebind(#20207,#20162)
|
||||
typebind(#20207,#20163)
|
||||
#20208=*
|
||||
stmts(#20208,1,#20204,-2,"{}")
|
||||
#20209=@"loc,{#10000},8,19,8,20"
|
||||
@@ -660,7 +660,7 @@ hasLocation(#20219,#20138)
|
||||
enclosing_stmt(#20219,#20217)
|
||||
expr_containers(#20219,#20001)
|
||||
literals("I","I",#20219)
|
||||
typedecl(#20219,#20163)
|
||||
typedecl(#20219,#20164)
|
||||
#20220=*
|
||||
properties(#20220,#20217,2,0,"method(this: I);")
|
||||
#20221=@"loc,{#10000},12,3,12,18"
|
||||
@@ -689,7 +689,7 @@ typeexprs(#20226,0,#20223,-4,"I")
|
||||
hasLocation(#20226,#20150)
|
||||
expr_containers(#20226,#20223)
|
||||
literals("I","I",#20226)
|
||||
typebind(#20226,#20163)
|
||||
typebind(#20226,#20164)
|
||||
is_method(#20220)
|
||||
is_abstract_member(#20220)
|
||||
#20227=*
|
||||
@@ -729,37 +729,37 @@ successor(#20203,#20204)
|
||||
successor(#20201,#20212)
|
||||
successor(#20199,#20203)
|
||||
successor(#20197,#20217)
|
||||
successor(#20188,#20199)
|
||||
successor(#20174,#20177)
|
||||
successor(#20178,#20175)
|
||||
successor(#20189,#20199)
|
||||
successor(#20175,#20178)
|
||||
successor(#20179,#20176)
|
||||
#20236=*
|
||||
entry_cfg_node(#20236,#20178)
|
||||
entry_cfg_node(#20236,#20179)
|
||||
#20237=@"loc,{#10000},3,9,3,8"
|
||||
locations_default(#20237,#10000,3,9,3,8)
|
||||
hasLocation(#20236,#20237)
|
||||
#20238=*
|
||||
exit_cfg_node(#20238,#20178)
|
||||
exit_cfg_node(#20238,#20179)
|
||||
#20239=@"loc,{#10000},3,45,3,44"
|
||||
locations_default(#20239,#10000,3,45,3,44)
|
||||
hasLocation(#20238,#20239)
|
||||
successor(#20186,#20238)
|
||||
successor(#20182,#20186)
|
||||
successor(#20236,#20182)
|
||||
successor(#20177,#20178)
|
||||
successor(#20175,#20188)
|
||||
successor(#20164,#20174)
|
||||
successor(#20187,#20238)
|
||||
successor(#20183,#20187)
|
||||
successor(#20236,#20183)
|
||||
successor(#20178,#20179)
|
||||
successor(#20176,#20189)
|
||||
successor(#20165,#20175)
|
||||
#20240=*
|
||||
entry_cfg_node(#20240,#20164)
|
||||
entry_cfg_node(#20240,#20165)
|
||||
hasLocation(#20240,#20228)
|
||||
#20241=*
|
||||
exit_cfg_node(#20241,#20164)
|
||||
exit_cfg_node(#20241,#20165)
|
||||
#20242=@"loc,{#10000},1,47,1,46"
|
||||
locations_default(#20242,#10000,1,47,1,46)
|
||||
hasLocation(#20241,#20242)
|
||||
successor(#20172,#20241)
|
||||
successor(#20168,#20172)
|
||||
successor(#20240,#20168)
|
||||
successor(#20165,#20164)
|
||||
successor(#20227,#20165)
|
||||
successor(#20173,#20241)
|
||||
successor(#20169,#20173)
|
||||
successor(#20240,#20169)
|
||||
successor(#20166,#20165)
|
||||
successor(#20227,#20166)
|
||||
numlines(#10000,14,9,0)
|
||||
filetype(#10000,"typescript")
|
||||
|
||||
@@ -147,4 +147,3 @@ ql/javascript/ql/src/meta/extraction-metrics/FileData.ql
|
||||
ql/javascript/ql/src/meta/extraction-metrics/MissingMetrics.ql
|
||||
ql/javascript/ql/src/meta/extraction-metrics/PhaseTimings.ql
|
||||
ql/javascript/ql/src/meta/types/TypedExprs.ql
|
||||
ql/javascript/ql/src/meta/types/TypesWithQualifiedName.ql
|
||||
|
||||
@@ -153,17 +153,7 @@ private predicate jsdocTypeLookup(JSDocNamedTypeExpr ref, AstNode decl, string k
|
||||
kind = "T"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an element, of kind `kind`, that element `e` uses, if any.
|
||||
*
|
||||
* The `kind` is a string representing what kind of use it is:
|
||||
* - `"M"` for function and method calls
|
||||
* - `"T"` for uses of types
|
||||
* - `"V"` for variable accesses
|
||||
* - `"I"` for imports
|
||||
*/
|
||||
cached
|
||||
AstNode definitionOf(Locatable e, string kind) {
|
||||
private AstNode definitionOfRaw(Locatable e, string kind) {
|
||||
variableDefLookup(e, result, kind)
|
||||
or
|
||||
// prefer definitions over declarations
|
||||
@@ -179,3 +169,46 @@ AstNode definitionOf(Locatable e, string kind) {
|
||||
or
|
||||
jsdocTypeLookup(e, result, kind)
|
||||
}
|
||||
|
||||
/** Gets a more useful node to show for something that resolves to `node`. */
|
||||
private AstNode redirectOnce(AstNode node) {
|
||||
exists(ConstructorDeclaration ctor |
|
||||
ctor.isSynthetic() and
|
||||
node = ctor.getBody() and
|
||||
result = ctor.getDeclaringClass()
|
||||
)
|
||||
or
|
||||
exists(ClassDefinition cls |
|
||||
node = cls and
|
||||
result = cls.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(FunctionDeclStmt decl |
|
||||
node = decl and
|
||||
result = decl.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(MethodDeclaration member |
|
||||
not member instanceof ConstructorDeclaration and
|
||||
node = member.getBody() and
|
||||
result = member.getNameExpr()
|
||||
)
|
||||
}
|
||||
|
||||
private AstNode redirect(AstNode node) {
|
||||
node = definitionOfRaw(_, _) and
|
||||
result = redirectOnce*(node) and
|
||||
not exists(redirectOnce(result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an element, of kind `kind`, that element `e` uses, if any.
|
||||
*
|
||||
* The `kind` is a string representing what kind of use it is:
|
||||
* - `"M"` for function and method calls
|
||||
* - `"T"` for uses of types
|
||||
* - `"V"` for variable accesses
|
||||
* - `"I"` for imports
|
||||
*/
|
||||
cached
|
||||
AstNode definitionOf(Locatable e, string kind) { result = redirect(definitionOfRaw(e, kind)) }
|
||||
|
||||
@@ -649,11 +649,13 @@ module API {
|
||||
/** Gets a node corresponding to an import of module `m` without taking into account types from models. */
|
||||
Node getAModuleImportRaw(string m) {
|
||||
result = Impl::MkModuleImport(m) or
|
||||
result = Impl::MkModuleImport(m).(Node).getMember("default")
|
||||
result = Impl::MkModuleImport(m).(Node).getMember("default") or
|
||||
result = Impl::MkTypeUse(m, "")
|
||||
}
|
||||
|
||||
/** Gets a node whose type has the given qualified name, not including types from models. */
|
||||
Node getANodeOfTypeRaw(string moduleName, string exportedName) {
|
||||
exportedName != "" and
|
||||
result = Impl::MkTypeUse(moduleName, exportedName).(Node).getInstance()
|
||||
or
|
||||
exportedName = "" and
|
||||
@@ -749,18 +751,14 @@ module API {
|
||||
MkModuleImport(string m) {
|
||||
imports(_, m)
|
||||
or
|
||||
any(TypeAnnotation n).hasQualifiedName(m, _)
|
||||
or
|
||||
any(Type t).hasUnderlyingType(m, _)
|
||||
any(TypeAnnotation n).hasUnderlyingType(m, _)
|
||||
} or
|
||||
MkClassInstance(DataFlow::ClassNode cls) { needsDefNode(cls) } or
|
||||
MkDef(DataFlow::Node nd) { rhs(_, _, nd) } or
|
||||
MkUse(DataFlow::Node nd) { use(_, _, nd) } or
|
||||
/** A use of a TypeScript type. */
|
||||
MkTypeUse(string moduleName, string exportName) {
|
||||
any(TypeAnnotation n).hasQualifiedName(moduleName, exportName)
|
||||
or
|
||||
any(Type t).hasUnderlyingType(moduleName, exportName)
|
||||
any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName)
|
||||
} or
|
||||
MkSyntheticCallbackArg(DataFlow::Node src, int bound, DataFlow::InvokeNode nd) {
|
||||
trackUseNode(src, true, bound, "").flowsTo(nd.getCalleeNode())
|
||||
|
||||
@@ -5,17 +5,49 @@
|
||||
import javascript
|
||||
|
||||
module Closure {
|
||||
/** A call to `goog.require` */
|
||||
class RequireCallExpr extends CallExpr {
|
||||
RequireCallExpr() { this.getCallee().(PropAccess).getQualifiedName() = "goog.require" }
|
||||
|
||||
/** Gets the imported namespace name. */
|
||||
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
|
||||
}
|
||||
|
||||
/** A call to `goog.provide` */
|
||||
class ProvideCallExpr extends CallExpr {
|
||||
ProvideCallExpr() { this.getCallee().(PropAccess).getQualifiedName() = "goog.provide" }
|
||||
|
||||
/** Gets the imported namespace name. */
|
||||
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
|
||||
}
|
||||
|
||||
/** A call to `goog.module` or `goog.declareModuleId`. */
|
||||
private class ModuleDeclarationCall extends CallExpr {
|
||||
private string kind;
|
||||
|
||||
ModuleDeclarationCall() {
|
||||
this.getCallee().(PropAccess).getQualifiedName() = kind and
|
||||
kind = ["goog.module", "goog.declareModuleId"]
|
||||
}
|
||||
|
||||
/** Gets the declared namespace. */
|
||||
string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
|
||||
|
||||
/** Gets the string `goog.module` or `goog.declareModuleId` depending on which method is being called. */
|
||||
string getModuleKind() { result = kind }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to a Closure namespace.
|
||||
*/
|
||||
class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range {
|
||||
deprecated class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range {
|
||||
/**
|
||||
* Gets the namespace being referenced.
|
||||
*/
|
||||
string getClosureNamespace() { result = super.getClosureNamespace() }
|
||||
}
|
||||
|
||||
module ClosureNamespaceRef {
|
||||
deprecated module ClosureNamespaceRef {
|
||||
/**
|
||||
* A reference to a Closure namespace.
|
||||
*
|
||||
@@ -32,10 +64,10 @@ module Closure {
|
||||
/**
|
||||
* A data flow node that returns the value of a closure namespace.
|
||||
*/
|
||||
class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range {
|
||||
}
|
||||
deprecated class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range
|
||||
{ }
|
||||
|
||||
module ClosureNamespaceAccess {
|
||||
deprecated module ClosureNamespaceAccess {
|
||||
/**
|
||||
* A data flow node that returns the value of a closure namespace.
|
||||
*
|
||||
@@ -47,7 +79,7 @@ module Closure {
|
||||
/**
|
||||
* A call to a method on the `goog.` namespace, as a closure reference.
|
||||
*/
|
||||
abstract private class DefaultNamespaceRef extends DataFlow::MethodCallNode,
|
||||
abstract deprecated private class DefaultNamespaceRef extends DataFlow::MethodCallNode,
|
||||
ClosureNamespaceRef::Range
|
||||
{
|
||||
DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() }
|
||||
@@ -59,14 +91,14 @@ module Closure {
|
||||
* Holds if `node` is the data flow node corresponding to the expression in
|
||||
* a top-level expression statement.
|
||||
*/
|
||||
private predicate isTopLevelExpr(DataFlow::Node node) {
|
||||
deprecated private predicate isTopLevelExpr(DataFlow::Node node) {
|
||||
any(TopLevel tl).getAChildStmt().(ExprStmt).getExpr().flow() = node
|
||||
}
|
||||
|
||||
/**
|
||||
* A top-level call to `goog.provide`.
|
||||
*/
|
||||
private class DefaultClosureProvideCall extends DefaultNamespaceRef {
|
||||
deprecated private class DefaultClosureProvideCall extends DefaultNamespaceRef {
|
||||
DefaultClosureProvideCall() {
|
||||
this.getMethodName() = "provide" and
|
||||
isTopLevelExpr(this)
|
||||
@@ -76,13 +108,14 @@ module Closure {
|
||||
/**
|
||||
* A top-level call to `goog.provide`.
|
||||
*/
|
||||
class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall
|
||||
deprecated class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall
|
||||
{ }
|
||||
|
||||
/**
|
||||
* A call to `goog.require`.
|
||||
*/
|
||||
private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range
|
||||
deprecated private class DefaultClosureRequireCall extends DefaultNamespaceRef,
|
||||
ClosureNamespaceAccess::Range
|
||||
{
|
||||
DefaultClosureRequireCall() { this.getMethodName() = "require" }
|
||||
}
|
||||
@@ -90,13 +123,13 @@ module Closure {
|
||||
/**
|
||||
* A call to `goog.require`.
|
||||
*/
|
||||
class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall
|
||||
deprecated class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall
|
||||
{ }
|
||||
|
||||
/**
|
||||
* A top-level call to `goog.module` or `goog.declareModuleId`.
|
||||
*/
|
||||
private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef {
|
||||
deprecated private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef {
|
||||
DefaultClosureModuleDeclaration() {
|
||||
(this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and
|
||||
isTopLevelExpr(this)
|
||||
@@ -106,41 +139,29 @@ module Closure {
|
||||
/**
|
||||
* A top-level call to `goog.module` or `goog.declareModuleId`.
|
||||
*/
|
||||
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration
|
||||
deprecated class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration
|
||||
{ }
|
||||
|
||||
private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) }
|
||||
|
||||
pragma[nomagic]
|
||||
private MethodCallExpr googModuleDeclExpr() {
|
||||
result.getReceiver() = googVariable().getAnAccess() and
|
||||
result.getMethodName() = ["module", "declareModuleId"]
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private MethodCallExpr googModuleDeclExprInContainer(StmtContainer container) {
|
||||
result = googModuleDeclExpr() and
|
||||
container = result.getContainer()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private ClosureRequireCall getARequireInTopLevel(ClosureModule m) { result.getTopLevel() = m }
|
||||
private RequireCallExpr getARequireInTopLevel(ClosureModule m) { result.getTopLevel() = m }
|
||||
|
||||
/**
|
||||
* A module using the Closure module system, declared using `goog.module()` or `goog.declareModuleId()`.
|
||||
*/
|
||||
class ClosureModule extends Module {
|
||||
ClosureModule() { exists(googModuleDeclExprInContainer(this)) }
|
||||
private ModuleDeclarationCall decl;
|
||||
|
||||
ClosureModule() { decl.getTopLevel() = this }
|
||||
|
||||
/**
|
||||
* Gets the call to `goog.module` or `goog.declareModuleId` in this module.
|
||||
*/
|
||||
ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this }
|
||||
deprecated ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this }
|
||||
|
||||
/**
|
||||
* Gets the namespace of this module.
|
||||
*/
|
||||
string getClosureNamespace() { result = this.getModuleDeclaration().getClosureNamespace() }
|
||||
string getClosureNamespace() { result = decl.getClosureNamespace() }
|
||||
|
||||
override Module getAnImportedModule() {
|
||||
result.(ClosureModule).getClosureNamespace() =
|
||||
@@ -156,7 +177,7 @@ module Closure {
|
||||
* Has no result for ES6 modules using `goog.declareModuleId`.
|
||||
*/
|
||||
Variable getExportsVariable() {
|
||||
this.getModuleDeclaration().getMethodName() = "module" and
|
||||
decl.getModuleKind() = "goog.module" and
|
||||
result = this.getScope().getVariable("exports")
|
||||
}
|
||||
|
||||
@@ -185,15 +206,15 @@ module Closure {
|
||||
ClosureScript() {
|
||||
not this instanceof ClosureModule and
|
||||
(
|
||||
any(ClosureProvideCall provide).getTopLevel() = this
|
||||
any(ProvideCallExpr provide).getTopLevel() = this
|
||||
or
|
||||
any(ClosureRequireCall require).getTopLevel() = this
|
||||
any(RequireCallExpr require).getTopLevel() = this
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the identifier of a namespace required by this module. */
|
||||
string getARequiredNamespace() {
|
||||
exists(ClosureRequireCall require |
|
||||
exists(RequireCallExpr require |
|
||||
require.getTopLevel() = this and
|
||||
result = require.getClosureNamespace()
|
||||
)
|
||||
@@ -201,7 +222,7 @@ module Closure {
|
||||
|
||||
/** Gets the identifer of a namespace provided by this module. */
|
||||
string getAProvidedNamespace() {
|
||||
exists(ClosureProvideCall require |
|
||||
exists(ProvideCallExpr require |
|
||||
require.getTopLevel() = this and
|
||||
result = require.getClosureNamespace()
|
||||
)
|
||||
@@ -213,7 +234,13 @@ module Closure {
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate isClosureNamespace(string name) {
|
||||
exists(string namespace | namespace = any(ClosureNamespaceRef ref).getClosureNamespace() |
|
||||
exists(string namespace |
|
||||
namespace =
|
||||
[
|
||||
any(RequireCallExpr ref).getClosureNamespace(),
|
||||
any(ModuleDeclarationCall c).getClosureNamespace()
|
||||
]
|
||||
|
|
||||
name = namespace.substring(0, namespace.indexOf("."))
|
||||
or
|
||||
name = namespace
|
||||
|
||||
@@ -180,6 +180,9 @@ deprecated private class LiteralImportPath extends PathExpr, ConstantString {
|
||||
* ```
|
||||
*/
|
||||
class ImportSpecifier extends Expr, @import_specifier {
|
||||
/** Gets the import declaration in which this specifier appears. */
|
||||
ImportDeclaration getImportDeclaration() { result.getASpecifier() = this }
|
||||
|
||||
/** Gets the imported symbol; undefined for default and namespace import specifiers. */
|
||||
Identifier getImported() { result = this.getChildExpr(0) }
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
private import semmle.javascript.internal.TypeResolution
|
||||
|
||||
/**
|
||||
* A program element that is either an expression or a type annotation.
|
||||
@@ -1017,7 +1018,11 @@ class InvokeExpr extends @invokeexpr, Expr {
|
||||
* Note that the resolved function may be overridden in a subclass and thus is not
|
||||
* necessarily the actual target of this invocation at runtime.
|
||||
*/
|
||||
Function getResolvedCallee() { result = this.getResolvedCalleeName().getImplementation() }
|
||||
Function getResolvedCallee() {
|
||||
TypeResolution::callTarget(this, result)
|
||||
or
|
||||
result = this.getResolvedCalleeName().getImplementation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,7 +34,7 @@ module AccessPath {
|
||||
not this.accessesGlobal(_) and
|
||||
not this instanceof DataFlow::PropRead and
|
||||
not this instanceof PropertyProjection and
|
||||
not this instanceof Closure::ClosureNamespaceAccess and
|
||||
not this.asExpr() instanceof Closure::RequireCallExpr and
|
||||
not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter()) and
|
||||
not FlowSteps::identityFunctionStep(_, this)
|
||||
}
|
||||
@@ -139,8 +139,8 @@ module AccessPath {
|
||||
result = join(fromReference(prop.getBase(), root), "[number]")
|
||||
)
|
||||
or
|
||||
exists(Closure::ClosureNamespaceAccess acc | node = acc |
|
||||
result = acc.getClosureNamespace() and
|
||||
exists(Closure::RequireCallExpr req | node = req.flow() |
|
||||
result = req.getClosureNamespace() and
|
||||
root.isGlobal()
|
||||
)
|
||||
or
|
||||
|
||||
@@ -33,6 +33,9 @@ class JSDoc extends @jsdoc, Locatable {
|
||||
result.getTitle() = title
|
||||
}
|
||||
|
||||
/** Gets the element to which this JSDoc comment is attached */
|
||||
Documentable getDocumentedElement() { result.getDocumentation() = this }
|
||||
|
||||
override string toString() { result = this.getComment().toString() }
|
||||
}
|
||||
|
||||
@@ -299,6 +302,41 @@ class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr
|
||||
override predicate isRawFunction() { this.getName() = "Function" }
|
||||
}
|
||||
|
||||
private AstNode getAncestorInScope(Documentable doc) {
|
||||
any(JSDocLocalTypeAccess t).getJSDocComment() = doc.getDocumentation() and // restrict to cases where we need this
|
||||
result = doc.getParent()
|
||||
or
|
||||
exists(AstNode mid |
|
||||
mid = getAncestorInScope(doc) and
|
||||
not mid = any(Scope s).getScopeElement() and
|
||||
result = mid.getParent()
|
||||
)
|
||||
}
|
||||
|
||||
private Scope getScope(Documentable doc) { result.getScopeElement() = getAncestorInScope(doc) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate shouldResolveName(TopLevel top, string name) {
|
||||
exists(JSDocLocalTypeAccess access |
|
||||
access.getName() = name and
|
||||
access.getTopLevel() = top
|
||||
)
|
||||
}
|
||||
|
||||
private LexicalName getOwnLocal(Scope scope, string name, DeclarationSpace space) {
|
||||
scope = result.getScope() and
|
||||
name = result.getName() and
|
||||
space = result.getDeclarationSpace() and
|
||||
shouldResolveName(scope.getScopeElement().getTopLevel(), name) // restrict size of predicate
|
||||
}
|
||||
|
||||
private LexicalName resolveLocal(Scope scope, string name, DeclarationSpace space) {
|
||||
result = getOwnLocal(scope, name, space)
|
||||
or
|
||||
result = resolveLocal(scope.getOuterScope(), name, space) and
|
||||
not exists(getOwnLocal(scope, name, space))
|
||||
}
|
||||
|
||||
/**
|
||||
* An unqualified identifier in a JSDoc type expression.
|
||||
*
|
||||
@@ -311,6 +349,12 @@ class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr
|
||||
*/
|
||||
class JSDocLocalTypeAccess extends JSDocIdentifierTypeExpr {
|
||||
JSDocLocalTypeAccess() { not this = any(JSDocQualifiedTypeAccess a).getNameNode() }
|
||||
|
||||
/** Gets a variable, type-name, or namespace that this expression may resolve to. */
|
||||
LexicalName getALexicalName() {
|
||||
result =
|
||||
resolveLocal(getScope(this.getJSDocComment().getDocumentedElement()), this.getName(), _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,7 +415,7 @@ class JSDocNamedTypeExpr extends JSDocTypeExpr {
|
||||
* - `foo.bar.Baz` has prefix `foo` and suffix `.bar.Baz`.
|
||||
* - `Baz` has prefix `Baz` and an empty suffix.
|
||||
*/
|
||||
predicate hasNameParts(string prefix, string suffix) {
|
||||
deprecated predicate hasNameParts(string prefix, string suffix) {
|
||||
not this = any(JSDocQualifiedTypeAccess a).getBase() and // restrict size of predicate
|
||||
exists(string regex, string name | regex = "([^.]+)(.*)" |
|
||||
name = this.getRawName() and
|
||||
@@ -379,46 +423,6 @@ class JSDocNamedTypeExpr extends JSDocTypeExpr {
|
||||
suffix = name.regexpCapture(regex, 2)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
pragma[nomagic]
|
||||
private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) {
|
||||
// Force join ordering
|
||||
this.hasNameParts(prefix, suffix) and
|
||||
env.isContainerInScope(this.getContainer())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the qualified name of this name by resolving its prefix, if any.
|
||||
*/
|
||||
cached
|
||||
private string resolvedName() {
|
||||
exists(string prefix, string suffix, JSDoc::Environment env |
|
||||
this.hasNamePartsAndEnv(prefix, suffix, env) and
|
||||
result = env.resolveAlias(prefix) + suffix
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
globalName = this.resolvedName()
|
||||
or
|
||||
not exists(this.resolvedName()) and
|
||||
globalName = this.getRawName()
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
exists(string name |
|
||||
this.hasQualifiedName(name) and
|
||||
result.hasQualifiedName(name)
|
||||
)
|
||||
or
|
||||
// Handle case where a local variable has a reference to the class,
|
||||
// but the class doesn't have a globally qualified name.
|
||||
exists(string alias, JSDoc::Environment env |
|
||||
this.hasNamePartsAndEnv(alias, "", env) and
|
||||
result.getAClassReference().flowsTo(env.getNodeFromAlias(alias))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,12 +451,6 @@ class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
||||
* For example, in `Array<string>`, `string` is the only argument type.
|
||||
*/
|
||||
JSDocTypeExpr getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
this.getHead().hasQualifiedName(globalName)
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() { result = this.getHead().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,8 +470,6 @@ class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
|
||||
|
||||
override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -493,8 +489,6 @@ class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeE
|
||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
|
||||
|
||||
override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,8 +593,6 @@ class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTyp
|
||||
override JSDocTypeExpr getAnUnderlyingType() {
|
||||
result = this.getUnderlyingType().getAnUnderlyingType()
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() { result = this.getUnderlyingType().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -635,7 +627,7 @@ module JSDoc {
|
||||
/**
|
||||
* A statement container which may declare JSDoc name aliases.
|
||||
*/
|
||||
class Environment extends StmtContainer {
|
||||
deprecated class Environment extends StmtContainer {
|
||||
/**
|
||||
* Gets the fully qualified name aliased by the given unqualified name
|
||||
* within this container.
|
||||
@@ -685,7 +677,7 @@ module JSDoc {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isTypenamePrefix(string name) {
|
||||
deprecated private predicate isTypenamePrefix(string name) {
|
||||
any(JSDocNamedTypeExpr expr).hasNameParts(name, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
import javascript
|
||||
private import internal.StmtContainers
|
||||
private import internal.NameResolution
|
||||
private import internal.UnderlyingTypes
|
||||
|
||||
/**
|
||||
* A type annotation, either in the form of a TypeScript type or a JSDoc comment.
|
||||
@@ -75,14 +77,38 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer {
|
||||
TypeAnnotation getAnUnderlyingType() { result = this }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `hasUnderlyingType` instead.
|
||||
*
|
||||
* Holds if this is a reference to the type with qualified name `globalName` relative to the global scope.
|
||||
*/
|
||||
predicate hasQualifiedName(string globalName) { none() }
|
||||
deprecated predicate hasQualifiedName(string globalName) {
|
||||
UnderlyingTypes::nodeHasUnderlyingType(this, globalName)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `hasUnderlyingType` instead.
|
||||
*
|
||||
* Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`.
|
||||
*/
|
||||
predicate hasQualifiedName(string moduleName, string exportedName) { none() }
|
||||
deprecated predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a reference to the type with qualified name `globalName` relative to the global scope,
|
||||
* or is declared as a subtype thereof, or is a union or intersection containing such a type.
|
||||
*/
|
||||
final predicate hasUnderlyingType(string globalName) {
|
||||
UnderlyingTypes::nodeHasUnderlyingType(this, globalName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`,
|
||||
* or is declared as a subtype thereof, or is a union or intersection containing such a type.
|
||||
*/
|
||||
final predicate hasUnderlyingType(string moduleName, string exportedName) {
|
||||
UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName)
|
||||
}
|
||||
|
||||
/** Gets the statement in which this type appears. */
|
||||
Stmt getEnclosingStmt() { none() }
|
||||
@@ -107,5 +133,5 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer {
|
||||
*
|
||||
* This unfolds nullability modifiers and generic type applications.
|
||||
*/
|
||||
DataFlow::ClassNode getClass() { none() }
|
||||
final DataFlow::ClassNode getClass() { UnderlyingTypes::nodeHasUnderlyingClassType(this, result) }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import javascript
|
||||
private import semmle.javascript.internal.UnderlyingTypes
|
||||
|
||||
/**
|
||||
* A statement that defines a namespace, that is, a namespace declaration or enum declaration.
|
||||
@@ -575,10 +576,6 @@ class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation {
|
||||
override Function getEnclosingFunction() { result = ExprOrType.super.getEnclosingFunction() }
|
||||
|
||||
override TopLevel getTopLevel() { result = ExprOrType.super.getTopLevel() }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result.getAstNode() = this.getType().(ClassType).getClass()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,58 +695,9 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef {
|
||||
*/
|
||||
TypeName getTypeName() { ast_node_symbol(this, result) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
this.getTypeName().hasQualifiedName(globalName)
|
||||
or
|
||||
exists(LocalTypeAccess local | local = this |
|
||||
not exists(local.getLocalTypeName()) and // Without a local type name, the type is looked up in the global scope.
|
||||
globalName = local.getName()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
this.getTypeName().hasQualifiedName(moduleName, exportedName)
|
||||
or
|
||||
exists(ImportDeclaration imprt, ImportSpecifier spec |
|
||||
moduleName = getImportName(imprt) and
|
||||
spec = imprt.getASpecifier()
|
||||
|
|
||||
spec.getImportedName() = exportedName and
|
||||
this = spec.getLocal().(TypeDecl).getLocalTypeName().getAnAccess()
|
||||
or
|
||||
(spec instanceof ImportNamespaceSpecifier or spec instanceof ImportDefaultSpecifier) and
|
||||
this =
|
||||
spec.getLocal().(LocalNamespaceDecl).getLocalNamespaceName().getAMemberAccess(exportedName)
|
||||
)
|
||||
or
|
||||
exists(ImportEqualsDeclaration imprt |
|
||||
moduleName = getImportName(imprt.getImportedEntity()) and
|
||||
this =
|
||||
imprt
|
||||
.getIdentifier()
|
||||
.(LocalNamespaceDecl)
|
||||
.getLocalNamespaceName()
|
||||
.getAMemberAccess(exportedName)
|
||||
)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeAccess" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a suitable name for the library imported by `imprt`.
|
||||
*
|
||||
* For relative imports, this is the snapshot-relative path to the imported module.
|
||||
* For non-relative imports, it is the import path itself.
|
||||
*/
|
||||
private string getImportName(Import imprt) {
|
||||
exists(string path | path = imprt.getImportedPathString() |
|
||||
if path.regexpMatch("[./].*")
|
||||
then result = imprt.getImportedModule().getFile().getRelativePath()
|
||||
else result = path
|
||||
)
|
||||
}
|
||||
|
||||
/** An identifier that is used as part of a type, such as `Date`. */
|
||||
class LocalTypeAccess extends @local_type_access, TypeAccess, Identifier, LexicalAccess {
|
||||
override predicate isStringy() { this.getName() = "String" }
|
||||
@@ -822,14 +770,6 @@ class GenericTypeExpr extends @generic_typeexpr, TypeExpr {
|
||||
/** Gets the number of type arguments. This is always at least one. */
|
||||
int getNumTypeArgument() { result = count(this.getATypeArgument()) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
this.getTypeAccess().hasQualifiedName(globalName)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
this.getTypeAccess().hasQualifiedName(moduleName, exportedName)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GenericTypeExpr" }
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ class Scope extends @scope {
|
||||
result = this.getAVariable() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
/** Gets the local type name with the given name declared in this scope. */
|
||||
LocalTypeName getLocalTypeName(string name) {
|
||||
result.getScope() = this and
|
||||
result.getName() = name
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,8 +134,26 @@ class Variable extends @variable, LexicalName {
|
||||
/** Gets the scope this variable is declared in. */
|
||||
override Scope getScope() { variables(this, _, result) }
|
||||
|
||||
/**
|
||||
* Holds if this variable is declared in the top-level of a module using a `declare` statement.
|
||||
*
|
||||
* For example:
|
||||
* ```js
|
||||
* declare var $: any;
|
||||
* ```
|
||||
*
|
||||
* Such variables are generally treated as a global variables, except for type-checking related purposes.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isTopLevelWithAmbientDeclaration() {
|
||||
this.getScope() instanceof ModuleScope and
|
||||
forex(VarDecl decl | decl = this.getADeclaration() | decl.isAmbient())
|
||||
}
|
||||
|
||||
/** Holds if this is a global variable. */
|
||||
predicate isGlobal() { this.getScope() instanceof GlobalScope }
|
||||
predicate isGlobal() {
|
||||
this.getScope() instanceof GlobalScope or this.isTopLevelWithAmbientDeclaration()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a variable exported from a TypeScript namespace.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.TypeResolution
|
||||
|
||||
/**
|
||||
* An input to a view component, such as React props.
|
||||
@@ -14,34 +15,11 @@ abstract class ViewComponentInput extends DataFlow::Node {
|
||||
|
||||
private class ViewComponentInputAsThreatModelSource extends ThreatModelSource::Range instanceof ViewComponentInput
|
||||
{
|
||||
ViewComponentInputAsThreatModelSource() { not isSafeType(this.asExpr().getType()) }
|
||||
ViewComponentInputAsThreatModelSource() {
|
||||
not TypeResolution::valueHasSanitizingPrimitiveType(this.asExpr())
|
||||
}
|
||||
|
||||
final override string getThreatModel() { result = "view-component-input" }
|
||||
|
||||
final override string getSourceType() { result = ViewComponentInput.super.getSourceType() }
|
||||
}
|
||||
|
||||
private predicate isSafeType(Type t) {
|
||||
t instanceof NumberLikeType
|
||||
or
|
||||
t instanceof BooleanLikeType
|
||||
or
|
||||
t instanceof UndefinedType
|
||||
or
|
||||
t instanceof NullType
|
||||
or
|
||||
t instanceof VoidType
|
||||
or
|
||||
hasSafeTypes(t, t.(UnionType).getNumElementType())
|
||||
or
|
||||
isSafeType(t.(IntersectionType).getAnElementType())
|
||||
}
|
||||
|
||||
/** Hold if the first `n` components of `t` are safe types. */
|
||||
private predicate hasSafeTypes(UnionType t, int n) {
|
||||
isSafeType(t.getElementType(0)) and
|
||||
n = 1
|
||||
or
|
||||
isSafeType(t.getElementType(n - 1)) and
|
||||
hasSafeTypes(t, n - 1)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ private import internal.PreCallGraphStep
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
private import semmle.javascript.dataflow.internal.DataFlowPrivate as Private
|
||||
private import semmle.javascript.dataflow.internal.VariableOrThis
|
||||
private import semmle.javascript.internal.NameResolution
|
||||
private import semmle.javascript.internal.UnderlyingTypes
|
||||
private import semmle.javascript.internal.TypeResolution
|
||||
|
||||
module DataFlow {
|
||||
/**
|
||||
@@ -189,26 +192,6 @@ module DataFlow {
|
||||
FlowSteps::identityFunctionStep(result, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the static type of this node as determined by the TypeScript type system.
|
||||
*/
|
||||
private Type getType() {
|
||||
exists(AST::ValueNode node |
|
||||
this = TValueNode(node) and
|
||||
ast_node_type(node, result)
|
||||
)
|
||||
or
|
||||
exists(BindingPattern pattern |
|
||||
this = lvalueNode(pattern) and
|
||||
ast_node_type(pattern, result)
|
||||
)
|
||||
or
|
||||
exists(MethodDefinition def |
|
||||
this = TThisNode(def.getInit()) and
|
||||
ast_node_type(def.getDeclaringClass(), result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type annotation describing the type of this node,
|
||||
* provided that a static type could not be found.
|
||||
@@ -229,6 +212,15 @@ module DataFlow {
|
||||
)
|
||||
}
|
||||
|
||||
private NameResolution::Node getNameResolutionNode() {
|
||||
this = valueNode(result)
|
||||
or
|
||||
exists(PropertyPattern pattern |
|
||||
result = pattern.getValuePattern() and
|
||||
this = TPropNode(pattern)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is annotated with the given named type,
|
||||
* or is declared as a subtype thereof, or is a union or intersection containing such a type.
|
||||
@@ -236,9 +228,10 @@ module DataFlow {
|
||||
cached
|
||||
predicate hasUnderlyingType(string globalName) {
|
||||
Stages::TypeTracking::ref() and
|
||||
this.getType().hasUnderlyingType(globalName)
|
||||
or
|
||||
this.getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(globalName)
|
||||
exists(NameResolution::Node type |
|
||||
TypeResolution::valueHasType(this.getNameResolutionNode(), type) and
|
||||
UnderlyingTypes::nodeHasUnderlyingType(type, globalName)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,9 +241,11 @@ module DataFlow {
|
||||
cached
|
||||
predicate hasUnderlyingType(string moduleName, string typeName) {
|
||||
Stages::TypeTracking::ref() and
|
||||
this.getType().hasUnderlyingType(moduleName, typeName)
|
||||
or
|
||||
this.getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(moduleName, typeName)
|
||||
moduleName != "global" and
|
||||
exists(NameResolution::Node type |
|
||||
TypeResolution::valueHasType(this.getNameResolutionNode(), type) and
|
||||
UnderlyingTypes::nodeHasUnderlyingType(type, moduleName, typeName)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -333,7 +333,14 @@ module SourceNode {
|
||||
astNode instanceof TaggedTemplateExpr or
|
||||
astNode instanceof Templating::PipeRefExpr or
|
||||
astNode instanceof Templating::TemplateVarRefExpr or
|
||||
astNode instanceof StringLiteral
|
||||
astNode instanceof StringLiteral or
|
||||
astNode instanceof TypeAssertion or
|
||||
astNode instanceof SatisfiesExpr
|
||||
)
|
||||
or
|
||||
exists(VariableDeclarator decl |
|
||||
exists(decl.getTypeAnnotation()) and
|
||||
this = DataFlow::valueNode(decl.getBindingPattern())
|
||||
)
|
||||
or
|
||||
DataFlow::parameterNode(this, _)
|
||||
|
||||
@@ -179,6 +179,9 @@ module Public {
|
||||
/** Holds if this represents values stored at an unknown array index. */
|
||||
predicate isUnknownArrayElement() { this = MkArrayElementUnknown() }
|
||||
|
||||
/** Holds if this represents the value of a resolved promise. */
|
||||
predicate isPromiseValue() { this = MkPromiseValue() }
|
||||
|
||||
/** Holds if this represents values stored in a `Map` at an unknown key. */
|
||||
predicate isMapValueWithUnknownKey() { this = MkMapValueWithUnknownKey() }
|
||||
|
||||
@@ -266,6 +269,11 @@ module Public {
|
||||
or
|
||||
this = ContentSet::anyCapturedContent() and
|
||||
result instanceof Private::MkCapturedContent
|
||||
or
|
||||
// Although data flow will never use the special `Awaited` ContentSet in a read or store step,
|
||||
// it may appear in type-tracking and type resolution, and here it helps to treat is as `Awaited[value]`.
|
||||
this = MkAwaited() and
|
||||
result = MkPromiseValue()
|
||||
}
|
||||
|
||||
/** Gets the singleton content to be accessed. */
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import javascript
|
||||
private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
private import semmle.javascript.internal.NameResolution
|
||||
private import semmle.javascript.internal.TypeResolution
|
||||
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about [Nest](https://nestjs.com/).
|
||||
@@ -133,7 +135,9 @@ module NestJS {
|
||||
hasSanitizingPipe(this, false)
|
||||
or
|
||||
hasSanitizingPipe(this, true) and
|
||||
isSanitizingType(this.getParameter().getType().unfold())
|
||||
// Note: we could consider types with class-validator decorators to be sanitized here, but instead we consider the root
|
||||
// object to be tainted, but omit taint steps for the individual properties names that have sanitizing decorators. See ClassValidator.qll.
|
||||
TypeResolution::isSanitizingPrimitiveType(this.getParameter().getTypeAnnotation())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,19 +213,6 @@ module NestJS {
|
||||
dependsOnType = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a parameter of type `t` is considered sanitized, provided it has been checked by `ValidationPipe`
|
||||
* (which relies on metadata emitted by the TypeScript compiler).
|
||||
*/
|
||||
private predicate isSanitizingType(Type t) {
|
||||
t instanceof NumberType
|
||||
or
|
||||
t instanceof BooleanType
|
||||
//
|
||||
// Note: we could consider types with class-validator decorators to be sanitized here, but instead we consider the root
|
||||
// object to be tainted, but omit taint steps for the individual properties names that have sanitizing decorators. See ClassValidator.qll.
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined pipe class, for example:
|
||||
* ```js
|
||||
@@ -237,7 +228,7 @@ module NestJS {
|
||||
CustomPipeClass() {
|
||||
exists(ClassDefinition cls |
|
||||
this = cls.flow() and
|
||||
cls.getASuperInterface().hasQualifiedName("@nestjs/common", "PipeTransform")
|
||||
cls.getASuperInterface().hasUnderlyingType("@nestjs/common", "PipeTransform")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -327,14 +318,6 @@ module NestJS {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isStringType(Type type) {
|
||||
type instanceof StringType
|
||||
or
|
||||
type instanceof AnyType
|
||||
or
|
||||
isStringType(type.(PromiseType).getElementType().unfold())
|
||||
}
|
||||
|
||||
/**
|
||||
* A return value from a route handler, seen as an argument to `res.send()`.
|
||||
*
|
||||
@@ -353,10 +336,10 @@ module NestJS {
|
||||
ReturnValueAsResponseSend() {
|
||||
handler.isReturnValueReflected() and
|
||||
this = handler.getAReturn() and
|
||||
// Only returned strings are sinks
|
||||
not exists(Type type |
|
||||
type = this.asExpr().getType() and
|
||||
not isStringType(type.unfold())
|
||||
// Only returned strings are sinks. If we can find a type for the return value, it must be string-like.
|
||||
not exists(NameResolution::Node type |
|
||||
TypeResolution::valueHasType(this.asExpr(), type) and
|
||||
not TypeResolution::hasUnderlyingStringOrAnyType(type)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,9 +60,7 @@ predicate isPackageUsed(string package) {
|
||||
or
|
||||
package = any(JS::Import imp).getImportedPathString()
|
||||
or
|
||||
any(JS::TypeName t).hasQualifiedName(package, _)
|
||||
or
|
||||
any(JS::TypeAnnotation t).hasQualifiedName(package, _)
|
||||
any(JS::TypeAnnotation t).hasUnderlyingType(package, _)
|
||||
or
|
||||
exists(JS::PackageJson json | json.getPackageName() = package)
|
||||
}
|
||||
@@ -138,7 +136,7 @@ API::Node getExtraNodeFromType(string type) {
|
||||
parseRelevantTypeString(type, package, qualifiedName)
|
||||
|
|
||||
qualifiedName = "" and
|
||||
result = [API::moduleImport(package), API::moduleExport(package)]
|
||||
result = [API::Internal::getAModuleImportRaw(package), API::moduleExport(package)]
|
||||
or
|
||||
// Access instance of a type based on type annotations
|
||||
result = API::Internal::getANodeOfTypeRaw(package, qualifiedName)
|
||||
|
||||
@@ -60,11 +60,7 @@ private predicate neverReturnsJQuery(string name) {
|
||||
decl.getBaseName() = "jQuery" and
|
||||
decl.getName() = name
|
||||
|
|
||||
not decl.getDocumentation()
|
||||
.getATagByTitle("return")
|
||||
.getType()
|
||||
.getAnUnderlyingType()
|
||||
.hasQualifiedName("jQuery")
|
||||
not decl.getDocumentation().getATagByTitle("return").getType().hasUnderlyingType("jQuery")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -414,6 +410,8 @@ module JQuery {
|
||||
this = DataFlow::moduleImport(["jquery", "zepto", "cash-dom"])
|
||||
or
|
||||
this.hasUnderlyingType("JQueryStatic")
|
||||
or
|
||||
this.hasUnderlyingType("jquery", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
512
javascript/ql/lib/semmle/javascript/internal/NameResolution.qll
Normal file
512
javascript/ql/lib/semmle/javascript/internal/NameResolution.qll
Normal file
@@ -0,0 +1,512 @@
|
||||
/**
|
||||
* Provides name resolution and propagates type information.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
/**
|
||||
* Provides name resolution and propagates type information.
|
||||
*/
|
||||
module NameResolution {
|
||||
private class NodeBase =
|
||||
@expr or @typeexpr or @lexical_name or @toplevel or @function_decl_stmt or @class_decl_stmt or
|
||||
@namespace_declaration or @enum_declaration or @interface_declaration or
|
||||
@type_alias_declaration or @jsdoc_type_expr;
|
||||
|
||||
/**
|
||||
* A node in a graph which we use to perform name and type resolution.
|
||||
*/
|
||||
class Node extends NodeBase {
|
||||
string toString() {
|
||||
result = this.(AstNode).toString()
|
||||
or
|
||||
result = this.(LexicalName).toString()
|
||||
or
|
||||
result = this.(JSDocTypeExpr).toString()
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
result = this.(AstNode).getLocation()
|
||||
or
|
||||
result = this.(LocalVariableLike).getLocation()
|
||||
or
|
||||
result = this.(JSDocTypeExpr).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
private signature predicate nodeSig(Node node);
|
||||
|
||||
/**
|
||||
* A module top-level, or a `module {}` or `enum {}` statement.
|
||||
*/
|
||||
private class ModuleLike extends AstNode {
|
||||
ModuleLike() {
|
||||
this instanceof Module
|
||||
or
|
||||
this instanceof NamespaceDefinition // `module {}` or `enum {}` statement
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A local variable, or a top-level variable that acts as a global variable due to an ambient declaration.
|
||||
*/
|
||||
class LocalVariableLike extends Variable {
|
||||
LocalVariableLike() { this.isLocal() or this.isTopLevelWithAmbientDeclaration() }
|
||||
|
||||
Location getLocation() {
|
||||
result =
|
||||
min(Location loc |
|
||||
loc = this.getADeclaration().getLocation()
|
||||
|
|
||||
loc order by loc.getStartLine(), loc.getStartColumn()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values/namespaces/types in `node1` can flow to values/namespaces/types in `node2`.
|
||||
*
|
||||
* May also include some type-specific steps in cases where this is harmless when tracking values.
|
||||
*/
|
||||
private predicate commonStep(Node node1, Node node2) {
|
||||
// Import paths are part of the graph and has an incoming edge from the imported module, if found.
|
||||
// This ensures we can also use the PathExpr as a source when working with external (unresolved) modules.
|
||||
exists(Import imprt |
|
||||
node1 = imprt.getImportedModule() and
|
||||
node2 = imprt.getImportedPathExpr()
|
||||
)
|
||||
or
|
||||
exists(ImportNamespaceSpecifier spec |
|
||||
node1 = spec.getImportDeclaration().getImportedPathExpr() and
|
||||
node2 = spec.getLocal()
|
||||
)
|
||||
or
|
||||
exists(ExportNamespaceSpecifier spec |
|
||||
node1 = spec.getExportDeclaration().(ReExportDeclaration).getImportedPath() and
|
||||
node2 = spec
|
||||
)
|
||||
or
|
||||
exists(ExportAssignDeclaration assign |
|
||||
node1 = assign.getExpression() and
|
||||
node2 = assign.getContainer()
|
||||
)
|
||||
or
|
||||
exists(ImportEqualsDeclaration imprt |
|
||||
node1 = imprt.getImportedEntity() and
|
||||
node2 = imprt.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(ExternalModuleReference ref |
|
||||
node1 = ref.getImportedPathExpr() and
|
||||
node2 = ref
|
||||
)
|
||||
or
|
||||
exists(ImportTypeExpr imprt |
|
||||
node1 = imprt.getPathExpr() and // TODO: ImportTypeExpr does not seem to be resolved to a Module
|
||||
node2 = imprt
|
||||
)
|
||||
or
|
||||
exists(ClassOrInterface cls |
|
||||
node1 = cls and
|
||||
node2 = cls.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(NamespaceDefinition def |
|
||||
node1 = def and
|
||||
node2 = def.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(Function fun |
|
||||
node1 = fun and
|
||||
node2 = fun.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(EnumMember def |
|
||||
node1 = def.getInitializer() and
|
||||
node2 = def.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(TypeAliasDeclaration alias |
|
||||
node1 = alias.getDefinition() and
|
||||
node2 = alias.getIdentifier()
|
||||
)
|
||||
or
|
||||
exists(VariableDeclarator decl |
|
||||
node1 = decl.getInit() and
|
||||
node2 = decl.getBindingPattern()
|
||||
)
|
||||
or
|
||||
exists(ParenthesizedTypeExpr type |
|
||||
node1 = type.getElementType() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(ParenthesisExpr expr |
|
||||
node1 = expr.getExpression() and
|
||||
node2 = expr
|
||||
)
|
||||
or
|
||||
exists(NonNullAssertion assertion |
|
||||
// For the time being we don't use this for nullness analysis, so just
|
||||
// propagate through these assertions.
|
||||
node1 = assertion.getExpression() and
|
||||
node2 = assertion
|
||||
)
|
||||
or
|
||||
exists(FunctionTypeExpr fun |
|
||||
node1 = fun.getFunction() and
|
||||
node2 = fun
|
||||
)
|
||||
or
|
||||
exists(TypeofTypeExpr type |
|
||||
node1 = type.getExpressionName() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(Closure::RequireCallExpr req |
|
||||
node1.(Closure::ClosureModule).getClosureNamespace() = req.getClosureNamespace() and
|
||||
node2 = req
|
||||
)
|
||||
or
|
||||
exists(Closure::ClosureModule mod |
|
||||
node1 = mod.getExportsVariable() and
|
||||
node2 = mod
|
||||
)
|
||||
or
|
||||
exists(ImmediatelyInvokedFunctionExpr fun, int i |
|
||||
node1 = fun.getArgument(i) and
|
||||
node2 = fun.getParameter(i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a read from `node1` to `node2` that accesses the member `name`.
|
||||
*/
|
||||
predicate readStep(Node node1, string name, Node node2) {
|
||||
exists(QualifiedTypeAccess access |
|
||||
node1 = access.getQualifier() and
|
||||
name = access.getIdentifier().getName() and
|
||||
node2 = access
|
||||
)
|
||||
or
|
||||
exists(QualifiedNamespaceAccess access |
|
||||
node1 = access.getQualifier() and
|
||||
name = access.getIdentifier().getName() and
|
||||
node2 = access
|
||||
)
|
||||
or
|
||||
exists(QualifiedVarTypeAccess access |
|
||||
node1 = access.getQualifier() and
|
||||
name = access.getIdentifier().getName() and
|
||||
node2 = access
|
||||
)
|
||||
or
|
||||
exists(PropAccess access |
|
||||
node1 = access.getBase() and
|
||||
name = access.getPropertyName() and
|
||||
node2 = access
|
||||
)
|
||||
or
|
||||
exists(ObjectPattern pattern |
|
||||
node1 = pattern and
|
||||
node2 = pattern.getPropertyPatternByName(name).getValuePattern()
|
||||
)
|
||||
or
|
||||
exists(ImportSpecifier spec |
|
||||
node1 = spec.getImportDeclaration().getImportedPathExpr() and
|
||||
name = spec.getImportedName() and
|
||||
node2 = spec.getLocal()
|
||||
)
|
||||
or
|
||||
exists(SelectiveReExportDeclaration exprt, ExportSpecifier spec |
|
||||
spec = exprt.getASpecifier() and
|
||||
node1 = exprt.getImportedPath() and
|
||||
name = spec.getLocalName() and
|
||||
node2 = spec.getLocal()
|
||||
)
|
||||
or
|
||||
exists(JSDocQualifiedTypeAccess expr |
|
||||
node1 = expr.getBase() and
|
||||
name = expr.getName() and
|
||||
node2 = expr
|
||||
)
|
||||
}
|
||||
|
||||
private signature module TypeResolutionInputSig {
|
||||
/**
|
||||
* Holds if flow is permitted through the given variable.
|
||||
*/
|
||||
predicate isRelevantVariable(LexicalName var);
|
||||
}
|
||||
|
||||
/**
|
||||
* A local variable with exactly one definition, not counting implicit initialization.
|
||||
*/
|
||||
private class EffectivelyConstantVariable extends LocalVariableLike {
|
||||
EffectivelyConstantVariable() {
|
||||
count(SsaExplicitDefinition ssa | ssa.getSourceVariable() = this) <= 1 // count may be zero if ambient
|
||||
}
|
||||
}
|
||||
|
||||
/** Configuration for propagating values and namespaces */
|
||||
private module ValueConfig implements TypeResolutionInputSig {
|
||||
predicate isRelevantVariable(LexicalName var) {
|
||||
var instanceof EffectivelyConstantVariable
|
||||
or
|
||||
// We merge the namespace and value declaration spaces as it seems there is
|
||||
// no need to distinguish them in practice.
|
||||
var instanceof LocalNamespaceName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information about values, such as references to a class, module, or namespace.
|
||||
*/
|
||||
module ValueFlow = FlowImpl<ValueConfig>;
|
||||
|
||||
private module TypeConfig implements TypeResolutionInputSig {
|
||||
predicate isRelevantVariable(LexicalName var) { var instanceof LocalTypeName }
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates nodes with information about types.
|
||||
*/
|
||||
module TypeFlow = FlowImpl<TypeConfig>;
|
||||
|
||||
/**
|
||||
* Generates a directed graph for tracking type names or value names back toward their definition.
|
||||
* The ultimate definition might not be in the database, but the graph lets us track as far as we can.
|
||||
*
|
||||
* The module parameter determines whether types or values should be tracked.
|
||||
*
|
||||
* The example below illustrates the need for two separate instantiations of this module.
|
||||
* When tracking through the nodes corresponding to `X`, we need to remember whether a type or value was tracked.
|
||||
*
|
||||
* ```ts
|
||||
* // lib.ts
|
||||
* class C1 {}
|
||||
* class C2 {}
|
||||
*
|
||||
* const X = C1;
|
||||
* type X = C2;
|
||||
*
|
||||
* export { X }
|
||||
*
|
||||
* // use.ts
|
||||
* import { X } from "./lib"
|
||||
*
|
||||
* var x1 = X // should refer to C1
|
||||
* var x2: X; // should refer to C2
|
||||
* ```
|
||||
*/
|
||||
private module FlowImpl<TypeResolutionInputSig S> {
|
||||
/**
|
||||
* Gets the exported member of `mod` named `name`.
|
||||
*/
|
||||
Node getModuleExport(ModuleLike mod, string name) {
|
||||
exists(ExportDeclaration exprt |
|
||||
mod = exprt.getContainer() and
|
||||
exprt.exportsAs(result, name) and
|
||||
S::isRelevantVariable(result)
|
||||
)
|
||||
or
|
||||
exists(ExportNamespaceSpecifier spec |
|
||||
result = spec and
|
||||
mod = spec.getContainer() and
|
||||
name = spec.getExportedName()
|
||||
)
|
||||
or
|
||||
exists(SelectiveReExportDeclaration exprt, ExportSpecifier spec |
|
||||
// `export { A as B } from 'blah'`
|
||||
// This is not covered by `exportsAs` above because neither A or B is a LexicalName
|
||||
// (both are property names) so it doesn't fit the interface of `exportsAs`.
|
||||
spec = exprt.getASpecifier() and
|
||||
mod = exprt.getContainer() and
|
||||
name = spec.getExportedName() and
|
||||
result = spec.getLocal()
|
||||
)
|
||||
or
|
||||
exists(EnumDeclaration enum |
|
||||
mod = enum and
|
||||
result = enum.getMemberByName(name).getIdentifier()
|
||||
)
|
||||
or
|
||||
storeToVariable(result, name, mod.(Closure::ClosureModule).getExportsVariable())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `value` is stored in `target.prop`. Only needs to recognise assignments
|
||||
* that are also recognised by JSDoc tooling such as the Closure compiler.
|
||||
*/
|
||||
private predicate storeToVariable(Expr value, string prop, LocalVariableLike target) {
|
||||
exists(AssignExpr assign |
|
||||
// target.name = value
|
||||
assign.getLhs().(PropAccess).accesses(target.getAnAccess(), prop) and
|
||||
value = assign.getRhs()
|
||||
)
|
||||
or
|
||||
// target = { name: value }
|
||||
value = target.getAnAssignedExpr().(ObjectExpr).getPropertyByName(prop).getInit()
|
||||
}
|
||||
|
||||
/** Steps that only apply for this configuration. */
|
||||
private predicate specificStep(Node node1, Node node2) {
|
||||
exists(LexicalName var | S::isRelevantVariable(var) |
|
||||
node1.(LexicalDecl).getALexicalName() = var and
|
||||
node2 = var
|
||||
or
|
||||
node1 = var and
|
||||
node2.(LexicalAccess).getALexicalName() = var
|
||||
or
|
||||
node1 = var and
|
||||
node2.(JSDocLocalTypeAccess).getALexicalName() = var
|
||||
)
|
||||
or
|
||||
exists(Node base, string name, ModuleLike mod |
|
||||
readStep(base, name, node2) and
|
||||
base = trackModule(mod) and
|
||||
node1 = getModuleExport(mod, name)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data should propagate from `node1` to `node2`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate step(Node node1, Node node2) {
|
||||
commonStep(node1, node2)
|
||||
or
|
||||
specificStep(node1, node2)
|
||||
}
|
||||
|
||||
/** Helps track flow from a particular set of source nodes. */
|
||||
module Track<nodeSig/1 isSource> {
|
||||
/** Gets the set of nodes reachable from `source`. */
|
||||
Node track(Node source) {
|
||||
isSource(source) and
|
||||
result = source
|
||||
or
|
||||
step(track(source), result)
|
||||
}
|
||||
}
|
||||
|
||||
signature class AstNodeSig extends AstNode;
|
||||
|
||||
/** Helps track flow from a particular set of source nodes. */
|
||||
module TrackNode<AstNodeSig Source> {
|
||||
/** Gets the set of nodes reachable from `source`. */
|
||||
Node track(Source source) {
|
||||
result = source
|
||||
or
|
||||
step(track(source), result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node to which the given module flows.
|
||||
*/
|
||||
predicate trackModule = ValueFlow::TrackNode<ModuleLike>::track/1;
|
||||
|
||||
/**
|
||||
* Holds if `moduleName` appears to start with a package name, as opposed to a relative file import.
|
||||
*/
|
||||
bindingset[moduleName]
|
||||
private predicate isExternalModuleName(string moduleName) {
|
||||
not moduleName.regexpMatch("^(\\.|/).*")
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
private string normalizeModuleName(string name) {
|
||||
result =
|
||||
name.regexpReplaceAll("^node:", "")
|
||||
.regexpReplaceAll("\\.[cm]?[jt]sx?$", "")
|
||||
.regexpReplaceAll("/(index)?$", "")
|
||||
}
|
||||
|
||||
/** Appends a name onto a qualified name */
|
||||
bindingset[a, b]
|
||||
string append(string a, string b) {
|
||||
if b = "default"
|
||||
then result = a
|
||||
else (
|
||||
(if a = "" or b = "" then result = a + b else result = a + "." + b) and
|
||||
result.length() < 100
|
||||
)
|
||||
}
|
||||
|
||||
private predicate needsQualifiedName(Node node) {
|
||||
node = any(JSDocLocalTypeAccess t).getALexicalName().(Variable)
|
||||
or
|
||||
exists(Node prev | needsQualifiedName(prev) |
|
||||
ValueFlow::step(node, prev)
|
||||
or
|
||||
readStep(node, _, prev)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is a reference to the given module, or a qualified name rooted in that module.
|
||||
*
|
||||
* If `qualifiedName` is empty, `node` refers to the module itself.
|
||||
*
|
||||
* If `mod` is the string `"global"`, `node` refers to a global access path.
|
||||
*
|
||||
* Unlike `trackModule`, this is intended to track uses of external packages.
|
||||
*/
|
||||
predicate nodeRefersToModule(Node node, string mod, string qualifiedName) {
|
||||
exists(Expr path |
|
||||
path = any(Import imprt).getImportedPathExpr() or
|
||||
path = any(ReExportDeclaration e).getImportedPath()
|
||||
|
|
||||
node = path and
|
||||
mod = normalizeModuleName(path.getStringValue()) and
|
||||
isExternalModuleName(mod) and
|
||||
qualifiedName = ""
|
||||
)
|
||||
or
|
||||
mod = "global" and
|
||||
exists(LocalNamespaceAccess access |
|
||||
node = access and
|
||||
not exists(access.getLocalNamespaceName()) and
|
||||
access.getName() = qualifiedName
|
||||
)
|
||||
or
|
||||
mod = "global" and
|
||||
exists(JSDocLocalTypeAccess access |
|
||||
node = access and
|
||||
not exists(access.getALexicalName()) and
|
||||
access.getName() = qualifiedName
|
||||
)
|
||||
or
|
||||
mod = "global" and
|
||||
exists(GlobalVarAccess access |
|
||||
node = access and
|
||||
needsQualifiedName(access) and // restrict number of qualified names we generate
|
||||
access.getName() = qualifiedName
|
||||
)
|
||||
or
|
||||
mod = "global" and
|
||||
qualifiedName = node.(Closure::RequireCallExpr).getClosureNamespace()
|
||||
or
|
||||
// Additionally track through bulk re-exports (`export * from 'mod`).
|
||||
// These are normally handled by 'exportAs' which supports various shadowing rules,
|
||||
// but has no effect when the ultimate re-exported module is not resolved to a Module.
|
||||
// We propagate external module refs through bulk re-exports and ignore shadowing rules.
|
||||
exists(BulkReExportDeclaration reExport |
|
||||
nodeRefersToModule(reExport.getImportedPath(), mod, qualifiedName) and
|
||||
node = reExport.getContainer()
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
nodeRefersToModule(mid, mod, qualifiedName) and
|
||||
ValueFlow::step(mid, node)
|
||||
)
|
||||
or
|
||||
exists(Node mid, string prefix, string step |
|
||||
nodeRefersToModule(mid, mod, prefix) and
|
||||
readStep(mid, step, node) and
|
||||
qualifiedName = append(prefix, step)
|
||||
)
|
||||
}
|
||||
}
|
||||
422
javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll
Normal file
422
javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll
Normal file
@@ -0,0 +1,422 @@
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.NameResolution::NameResolution
|
||||
private import semmle.javascript.internal.UnderlyingTypes
|
||||
private import semmle.javascript.dataflow.internal.sharedlib.SummaryTypeTracker as SummaryTypeTracker
|
||||
|
||||
module TypeResolution {
|
||||
predicate trackClassValue = ValueFlow::TrackNode<ClassDefinition>::track/1;
|
||||
|
||||
predicate trackType = TypeFlow::TrackNode<TypeDefinition>::track/1;
|
||||
|
||||
/**
|
||||
* Gets a node that has `fun` as an underlying type.
|
||||
*
|
||||
* We track through underlying types as an approximate way to handle calls to a type
|
||||
* that is a union/intersection involving functions.
|
||||
*/
|
||||
Node trackUnderlyingFunctionType(Function fun) {
|
||||
result = fun
|
||||
or
|
||||
exists(Node mid | mid = trackUnderlyingFunctionType(fun) |
|
||||
TypeFlow::step(mid, result)
|
||||
or
|
||||
UnderlyingTypes::underlyingTypeStep(mid, result)
|
||||
)
|
||||
}
|
||||
|
||||
predicate trackFunctionValue = ValueFlow::TrackNode<Function>::track/1;
|
||||
|
||||
/**
|
||||
* Gets the representative for the type containing the given member.
|
||||
*
|
||||
* For non-static members this is simply the enclosing type declaration.
|
||||
*
|
||||
* For static members we use the class's `Variable` as representative for the type of the class object.
|
||||
*/
|
||||
private Node getMemberBase(MemberDeclaration member) {
|
||||
if member.isStatic()
|
||||
then result = member.getDeclaringClass().getVariable()
|
||||
else result = member.getDeclaringType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `host` is a type with a `content` of type `memberType`, not counting inherited members.
|
||||
*/
|
||||
private predicate typeOwnMember(Node host, DataFlow::Content content, Node memberType) {
|
||||
exists(MemberDeclaration decl | host = getMemberBase(decl) |
|
||||
exists(FieldDeclaration field |
|
||||
decl = field and
|
||||
content.asPropertyName() = field.getName() and
|
||||
memberType = field.getTypeAnnotation()
|
||||
)
|
||||
or
|
||||
exists(MethodDeclaration method |
|
||||
decl = method and
|
||||
content.asPropertyName() = method.getName()
|
||||
|
|
||||
not method instanceof AccessorMethodDeclaration and
|
||||
memberType = method.getBody() // use the Function as representative for the function type
|
||||
or
|
||||
method instanceof GetterMethodDeclaration and
|
||||
memberType = method.getBody().getReturnTypeAnnotation()
|
||||
)
|
||||
or
|
||||
decl instanceof IndexSignature and
|
||||
memberType = decl.(IndexSignature).getBody().getReturnTypeAnnotation() and
|
||||
content.isUnknownArrayElement()
|
||||
)
|
||||
or
|
||||
// Ad-hoc support for array types. We don't support generics in general currently, we just special-case arrays and promises.
|
||||
content.isUnknownArrayElement() and
|
||||
(
|
||||
memberType = host.(ArrayTypeExpr).getElementType()
|
||||
or
|
||||
exists(GenericTypeExpr type |
|
||||
host = type and
|
||||
type.getTypeAccess().(LocalTypeAccess).getName() = ["Array", "ReadonlyArray"] and
|
||||
memberType = type.getTypeArgument(0)
|
||||
)
|
||||
or
|
||||
exists(JSDocAppliedTypeExpr type |
|
||||
host = type and
|
||||
type.getHead().(JSDocLocalTypeAccess).getName() = "Array" and
|
||||
memberType = type.getArgument(0)
|
||||
)
|
||||
)
|
||||
or
|
||||
content.isPromiseValue() and
|
||||
memberType = unwrapPromiseType(host)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `host` is a type with a `content` of type `memberType`, possible due to inheritance.
|
||||
*/
|
||||
private predicate typeMember(Node host, DataFlow::Content content, Node memberType) {
|
||||
typeOwnMember(host, content, memberType)
|
||||
or
|
||||
// Inherit members from base types
|
||||
not typeOwnMember(host, content, _) and
|
||||
exists(ClassOrInterface baseType | typeMember(baseType, content, memberType) |
|
||||
host.(ClassDefinition).getSuperClass() = trackClassValue(baseType)
|
||||
or
|
||||
host.(ClassOrInterface).getASuperInterface() = trackType(baseType)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds `use` refers to `host`, and `host` has type members.
|
||||
*
|
||||
* Currently steps through unions and intersections, which acts as a basic
|
||||
* approximation to the unions/intersection of objects.
|
||||
*/
|
||||
private predicate typeMemberHostReaches(Node host, Node use) {
|
||||
typeMember(host, _, _) and
|
||||
use = host
|
||||
or
|
||||
exists(Node mid | typeMemberHostReaches(host, mid) |
|
||||
TypeFlow::step(mid, use)
|
||||
or
|
||||
UnderlyingTypes::underlyingTypeStep(mid, use)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a read from from `object` to `member` that reads `contents`.
|
||||
*/
|
||||
private predicate valueReadStep(Node object, DataFlow::ContentSet contents, Node member) {
|
||||
member.(PropAccess).accesses(object, contents.asPropertyName())
|
||||
or
|
||||
object.(ObjectPattern).getPropertyPatternByName(contents.asPropertyName()).getValuePattern() =
|
||||
member
|
||||
or
|
||||
member.(AwaitExpr).getOperand() = object and
|
||||
contents = DataFlow::ContentSet::promiseValue()
|
||||
or
|
||||
SummaryTypeTracker::basicLoadStep(object.(AST::ValueNode).flow(),
|
||||
member.(AST::ValueNode).flow(), contents)
|
||||
}
|
||||
|
||||
predicate callTarget(InvokeExpr call, Function target) {
|
||||
exists(ClassDefinition cls |
|
||||
valueHasType(call.(NewExpr).getCallee(), trackClassValue(cls)) and
|
||||
target = cls.getConstructor().getBody()
|
||||
)
|
||||
or
|
||||
valueHasType(call.getCallee(), trackFunctionValue(target))
|
||||
or
|
||||
valueHasType(call.getCallee(), trackUnderlyingFunctionType(target)) and
|
||||
(
|
||||
call instanceof NewExpr and
|
||||
target = any(ConstructorTypeExpr t).getFunction()
|
||||
or
|
||||
call instanceof CallExpr and
|
||||
target = any(PlainFunctionTypeExpr t).getFunction()
|
||||
)
|
||||
or
|
||||
exists(InterfaceDefinition interface, CallSignature sig |
|
||||
valueHasType(call.getCallee(), trackType(interface)) and
|
||||
sig = interface.getACallSignature() and
|
||||
target = sig.getBody()
|
||||
|
|
||||
call instanceof NewExpr and
|
||||
sig instanceof ConstructorCallSignature
|
||||
or
|
||||
call instanceof CallExpr and
|
||||
sig instanceof FunctionCallSignature
|
||||
)
|
||||
}
|
||||
|
||||
private predicate functionReturnType(Function func, Node returnType) {
|
||||
returnType = func.getReturnTypeAnnotation()
|
||||
or
|
||||
not exists(func.getReturnTypeAnnotation()) and
|
||||
exists(Function functionType |
|
||||
contextualType(func, trackUnderlyingFunctionType(functionType)) and
|
||||
returnType = functionType.getReturnTypeAnnotation()
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
private predicate isPromiseTypeName(string name) {
|
||||
name.regexpMatch(".?(Promise|Thenable)(Like)?")
|
||||
}
|
||||
|
||||
private Node unwrapPromiseType(Node promiseType) {
|
||||
exists(GenericTypeExpr type |
|
||||
promiseType = type and
|
||||
isPromiseTypeName(type.getTypeAccess().(LocalTypeAccess).getName()) and
|
||||
result = type.getTypeArgument(0)
|
||||
)
|
||||
or
|
||||
exists(JSDocAppliedTypeExpr type |
|
||||
promiseType = type and
|
||||
isPromiseTypeName(type.getHead().(JSDocLocalTypeAccess).getName()) and
|
||||
result = type.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
predicate contextualType(Node value, Node type) {
|
||||
exists(LocalVariableLike v |
|
||||
type = v.getADeclaration().getTypeAnnotation() and
|
||||
value = v.getAnAssignedExpr()
|
||||
)
|
||||
or
|
||||
exists(InvokeExpr call, Function target, int i |
|
||||
callTarget(call, target) and
|
||||
value = call.getArgument(i) and
|
||||
type = target.getParameter(i).getTypeAnnotation()
|
||||
)
|
||||
or
|
||||
exists(Function lambda, Node returnType |
|
||||
value = lambda.getAReturnedExpr() and
|
||||
functionReturnType(lambda, returnType)
|
||||
|
|
||||
not lambda.isAsyncOrGenerator() and
|
||||
type = returnType
|
||||
or
|
||||
lambda.isAsync() and
|
||||
type = unwrapPromiseType(returnType)
|
||||
)
|
||||
or
|
||||
exists(ObjectExpr object, Node objectType, Node host, string name |
|
||||
contextualType(object, objectType) and
|
||||
typeMemberHostReaches(host, objectType) and
|
||||
typeMember(host, any(DataFlow::Content c | c.asPropertyName() = name), type) and
|
||||
value = object.getPropertyByName(name).getInit()
|
||||
)
|
||||
or
|
||||
exists(ArrayExpr array, Node arrayType, Node host |
|
||||
contextualType(array, arrayType) and
|
||||
typeMemberHostReaches(host, arrayType) and
|
||||
typeMember(host, any(DataFlow::Content c | c.isUnknownArrayElement()), type) and
|
||||
value = array.getAnElement()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `value` has the given `type`.
|
||||
*/
|
||||
predicate valueHasType(Node value, Node type) {
|
||||
value.(BindingPattern).getTypeAnnotation() = type
|
||||
or
|
||||
value.(TypeAssertion).getTypeAnnotation() = type
|
||||
or
|
||||
value.(SatisfiesExpr).getTypeAnnotation() = type
|
||||
or
|
||||
exists(VarDecl decl |
|
||||
// ValueFlow::step is restricted to variables with at most one assignment. Allow the type annotation
|
||||
// of a variable to propagate to its uses, even if the variable has multiple assignments.
|
||||
type = decl.getTypeAnnotation() and
|
||||
value = decl.getVariable().(LocalVariableLike).getAnAccess()
|
||||
)
|
||||
or
|
||||
exists(MemberDeclaration member |
|
||||
value.(ThisExpr).getBindingContainer() = member.getInit() and
|
||||
type = getMemberBase(member)
|
||||
)
|
||||
or
|
||||
exists(ClassDefinition cls |
|
||||
value = cls and
|
||||
type = cls.getVariable()
|
||||
)
|
||||
or
|
||||
exists(FunctionDeclStmt fun |
|
||||
value = fun and
|
||||
type = fun.getVariable()
|
||||
)
|
||||
or
|
||||
exists(Function target | callTarget(value, target) |
|
||||
type = target.getReturnTypeAnnotation()
|
||||
or
|
||||
exists(ClassDefinition cls |
|
||||
target = cls.getConstructor().getBody() and
|
||||
type = cls
|
||||
)
|
||||
)
|
||||
or
|
||||
// Contextual typing for parameters
|
||||
exists(Function lambda, Function functionType, int i |
|
||||
contextualType(lambda, trackUnderlyingFunctionType(functionType))
|
||||
or
|
||||
exists(InterfaceDefinition interface |
|
||||
contextualType(lambda, trackType(interface)) and
|
||||
functionType = interface.getACallSignature().getBody()
|
||||
)
|
||||
|
|
||||
value = lambda.getParameter(i) and
|
||||
not exists(value.(Parameter).getTypeAnnotation()) and
|
||||
type = functionType.getParameter(i).getTypeAnnotation()
|
||||
)
|
||||
or
|
||||
exists(Node mid | valueHasType(mid, type) | ValueFlow::step(mid, value))
|
||||
or
|
||||
exists(Node mid, Node midType, DataFlow::ContentSet contents, Node host |
|
||||
valueReadStep(mid, contents, value) and
|
||||
valueHasType(mid, midType) and
|
||||
typeMemberHostReaches(host, midType) and
|
||||
typeMember(host, contents.getAReadContent(), type)
|
||||
)
|
||||
}
|
||||
|
||||
signature predicate nodeSig(Node node);
|
||||
|
||||
/**
|
||||
* Tracks types that have a certain property, in the sense that:
|
||||
* - an intersection type has the property if any member has the property
|
||||
* - a union type has the property if all its members have the property
|
||||
*/
|
||||
module TrackMustProp<nodeSig/1 directlyHasProperty> {
|
||||
predicate hasProperty(Node node) {
|
||||
directlyHasProperty(node)
|
||||
or
|
||||
exists(Node mid |
|
||||
hasProperty(mid) and
|
||||
TypeFlow::step(mid, node)
|
||||
)
|
||||
or
|
||||
unionHasProp(node)
|
||||
or
|
||||
hasProperty(node.(IntersectionTypeExpr).getAnElementType())
|
||||
or
|
||||
exists(ConditionalTypeExpr cond |
|
||||
node = cond and
|
||||
hasProperty(cond.getTrueType()) and
|
||||
hasProperty(cond.getFalseType())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate unionHasProp(UnionTypeExpr node, int n) {
|
||||
hasProperty(node.getElementType(0)) and n = 1
|
||||
or
|
||||
unionHasProp(node, n - 1) and
|
||||
hasProperty(node.getElementType(n - 1))
|
||||
}
|
||||
|
||||
private predicate unionHasProp(UnionTypeExpr node) {
|
||||
unionHasProp(node, node.getNumElementType())
|
||||
}
|
||||
}
|
||||
|
||||
module ValueHasProperty<nodeSig/1 typeHasProperty> {
|
||||
predicate valueHasProperty(Node value) {
|
||||
exists(Node type |
|
||||
valueHasType(value, type) and
|
||||
typeHasProperty(type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isSanitizingPrimitiveTypeBase(Node node) {
|
||||
node.(TypeExpr).isNumbery()
|
||||
or
|
||||
node.(TypeExpr).isBooleany()
|
||||
or
|
||||
node.(TypeExpr).isNull()
|
||||
or
|
||||
node.(TypeExpr).isUndefined()
|
||||
or
|
||||
node.(TypeExpr).isVoid()
|
||||
or
|
||||
node.(TypeExpr).isNever()
|
||||
or
|
||||
node.(TypeExpr).isBigInt()
|
||||
or
|
||||
node.(TypeExpr).isSymbol()
|
||||
or
|
||||
node instanceof LiteralTypeExpr
|
||||
or
|
||||
node = any(EnumMember m).getIdentifier() // enum members are constant
|
||||
or
|
||||
node instanceof EnumDeclaration // enums are unions of constants
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` refers to a type that is considered untaintable (if actually enforced at runtime).
|
||||
*
|
||||
* Specifically, the types `number`, `boolean`, `null`, `undefined`, `void`, `never`, as well as literal types (`"foo"`)
|
||||
* and enums and enum members have this property.
|
||||
*/
|
||||
predicate isSanitizingPrimitiveType =
|
||||
TrackMustProp<isSanitizingPrimitiveTypeBase/1>::hasProperty/1;
|
||||
|
||||
/**
|
||||
* Holds if `value` has a type that is considered untaintable (if actually enforced at runtime).
|
||||
*
|
||||
* See `isSanitizingPrimitiveType`.
|
||||
*/
|
||||
predicate valueHasSanitizingPrimitiveType =
|
||||
ValueHasProperty<isSanitizingPrimitiveType/1>::valueHasProperty/1;
|
||||
|
||||
private predicate isPromiseBase(Node node) { exists(unwrapPromiseType(node)) }
|
||||
|
||||
/**
|
||||
* Holds if the given type is a Promise object. Does not hold for unions unless all parts of the union are promises.
|
||||
*/
|
||||
predicate isPromiseType = TrackMustProp<isPromiseBase/1>::hasProperty/1;
|
||||
|
||||
/**
|
||||
* Holds if the given value has a type that implied it is a Promise object. Does not hold for unions unless all parts of the union are promises.
|
||||
*/
|
||||
predicate valueHasPromiseType = ValueHasProperty<isPromiseType/1>::valueHasProperty/1;
|
||||
|
||||
/**
|
||||
* Holds if `type` contains `string` or `any`, possibly wrapped in a promise.
|
||||
*/
|
||||
predicate hasUnderlyingStringOrAnyType(Node type) {
|
||||
type.(TypeAnnotation).isStringy()
|
||||
or
|
||||
type.(TypeAnnotation).isAny()
|
||||
or
|
||||
type instanceof StringLiteralTypeExpr
|
||||
or
|
||||
type instanceof TemplateLiteralTypeExpr
|
||||
or
|
||||
exists(Node mid | hasUnderlyingStringOrAnyType(mid) |
|
||||
TypeFlow::step(mid, type)
|
||||
or
|
||||
UnderlyingTypes::underlyingTypeStep(mid, type)
|
||||
or
|
||||
type = unwrapPromiseType(mid)
|
||||
)
|
||||
}
|
||||
}
|
||||
128
javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll
Normal file
128
javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Provides name resolution and propagates type information.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.NameResolution::NameResolution
|
||||
|
||||
/**
|
||||
* Provides name resolution and propagates type information.
|
||||
*/
|
||||
module UnderlyingTypes {
|
||||
private predicate subtypeStep(Node node1, Node node2) {
|
||||
exists(ClassOrInterface cls |
|
||||
(
|
||||
node1 = cls.getSuperClass() or
|
||||
node1 = cls.getASuperInterface()
|
||||
) and
|
||||
node2 = cls
|
||||
)
|
||||
}
|
||||
|
||||
predicate underlyingTypeStep(Node node1, Node node2) {
|
||||
exists(UnionOrIntersectionTypeExpr type |
|
||||
node1 = type.getAnElementType() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(ReadonlyTypeExpr type |
|
||||
node1 = type.getElementType() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(OptionalTypeExpr type |
|
||||
node1 = type.getElementType() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(GenericTypeExpr type |
|
||||
node1 = type.getTypeAccess() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(ExpressionWithTypeArguments e |
|
||||
node1 = e.getExpression() and
|
||||
node2 = e
|
||||
)
|
||||
or
|
||||
exists(JSDocUnionTypeExpr type |
|
||||
node1 = type.getAnAlternative() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(JSDocNonNullableTypeExpr type |
|
||||
node1 = type.getTypeExpr() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(JSDocNullableTypeExpr type |
|
||||
node1 = type.getTypeExpr() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(JSDocAppliedTypeExpr type |
|
||||
node1 = type.getHead() and
|
||||
node2 = type
|
||||
)
|
||||
or
|
||||
exists(JSDocOptionalParameterTypeExpr type |
|
||||
node1 = type.getUnderlyingType() and
|
||||
node2 = type
|
||||
)
|
||||
}
|
||||
|
||||
predicate nodeHasUnderlyingType(Node node, string mod, string name) {
|
||||
nodeRefersToModule(node, mod, name)
|
||||
or
|
||||
exists(JSDocLocalTypeAccess type |
|
||||
node = type and
|
||||
not exists(type.getALexicalName()) and
|
||||
not type = any(JSDocQualifiedTypeAccess t).getBase() and
|
||||
name = type.getName() and
|
||||
mod = "global"
|
||||
)
|
||||
or
|
||||
exists(LocalTypeAccess type |
|
||||
node = type and
|
||||
not exists(type.getLocalTypeName()) and
|
||||
name = type.getName() and
|
||||
mod = "global"
|
||||
)
|
||||
or
|
||||
exists(Node mid | nodeHasUnderlyingType(mid, mod, name) |
|
||||
TypeFlow::step(mid, node)
|
||||
or
|
||||
underlyingTypeStep(mid, node)
|
||||
or
|
||||
subtypeStep(mid, node)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate nodeHasUnderlyingType(Node node, string name) {
|
||||
nodeHasUnderlyingType(node, "global", name)
|
||||
}
|
||||
|
||||
predicate nodeHasUnderlyingClassType(Node node, DataFlow::ClassNode cls) {
|
||||
node = cls.getAstNode()
|
||||
or
|
||||
exists(string name |
|
||||
classHasGlobalName(cls, name) and
|
||||
nodeHasUnderlyingType(node, name)
|
||||
)
|
||||
or
|
||||
exists(Node mid | nodeHasUnderlyingClassType(mid, cls) |
|
||||
TypeFlow::step(mid, node)
|
||||
or
|
||||
underlyingTypeStep(mid, node)
|
||||
// Note: unlike for external types, we do not use subtype steps here.
|
||||
// The caller is responsible for handling the class hierarchy.
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate classHasGlobalName(DataFlow::ClassNode cls, string name) {
|
||||
cls.flowsTo(AccessPath::getAnAssignmentTo(name)) and
|
||||
not cls.getTopLevel().isExterns() // don't propagate externs classes
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.internal.TypeResolution
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call to an `async` function.
|
||||
@@ -28,7 +29,7 @@ predicate isPromise(DataFlow::SourceNode node, boolean nullable) {
|
||||
isAsyncCall(node, nullable)
|
||||
or
|
||||
not isAsyncCall(node, _) and
|
||||
node.asExpr().getType() instanceof PromiseType and
|
||||
TypeResolution::valueHasPromiseType(node.asExpr()) and
|
||||
nullable = true
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ import javascript
|
||||
|
||||
from DataFlow::Node invoke, Function f, string kind
|
||||
where
|
||||
invoke.(DataFlow::InvokeNode).getACallee() = f and kind = "Call"
|
||||
or
|
||||
invoke.(DataFlow::PropRef).getAnAccessorCallee().getFunction() = f and kind = "Accessor call"
|
||||
(
|
||||
invoke.(DataFlow::InvokeNode).getACallee() = f and kind = "Call"
|
||||
or
|
||||
invoke.(DataFlow::PropRef).getAnAccessorCallee().getFunction() = f and kind = "Accessor call"
|
||||
) and
|
||||
not f.getTopLevel().isExterns()
|
||||
select invoke, kind + " to $@", f, f.describe()
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @name Types with qualified name
|
||||
* @description The number of type annotations with a qualified name
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/types-with-qualified-name
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import meta.MetaMetrics
|
||||
|
||||
select projectRoot(), count(TypeAnnotation t | t.hasQualifiedName(_) or t.hasQualifiedName(_, _))
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace NS {
|
||||
export class C {
|
||||
/** name:NS.C.m */
|
||||
m() { }
|
||||
}
|
||||
|
||||
export class D extends C { }
|
||||
}
|
||||
|
||||
function t1(c: NS.C, d: NS.D) {
|
||||
/** calls:NS.C.m */
|
||||
c.m();
|
||||
|
||||
/** calls:NS.C.m */
|
||||
d.m();
|
||||
}
|
||||
|
||||
async function t2(cp: Promise<NS.C>) {
|
||||
const c = await cp;
|
||||
/** calls:NS.C.m */
|
||||
c.m();
|
||||
|
||||
cp.then(c2 => {
|
||||
/** calls:NS.C.m */
|
||||
c2.m();
|
||||
})
|
||||
}
|
||||
@@ -1514,6 +1514,7 @@ sources
|
||||
| tst2.ts:7:1:9:1 | return of function setX |
|
||||
| tst2.ts:8:3:8:5 | A.x |
|
||||
| tst2.ts:11:11:11:13 | A.x |
|
||||
| tst2.ts:11:11:11:23 | A.x as number |
|
||||
| tst2.ts:13:1:13:40 | class S ... ing> {} |
|
||||
| tst2.ts:13:26:13:29 | List |
|
||||
| tst2.ts:13:39:13:38 | (...arg ... rgs); } |
|
||||
@@ -1522,6 +1523,7 @@ sources
|
||||
| tst2.ts:13:39:13:38 | super(...args) |
|
||||
| tst2.ts:13:39:13:38 | this |
|
||||
| tst2.ts:15:11:15:13 | A.x |
|
||||
| tst2.ts:15:11:15:30 | A.x satisfies number |
|
||||
| tst.js:1:1:1:0 | this |
|
||||
| tst.js:1:1:1:24 | import ... m 'fs'; |
|
||||
| tst.js:1:10:1:11 | fs |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
| bar.js:5:14:5:14 | x | x |
|
||||
| bar.js:5:14:5:14 | x | ns.very.long.namespace |
|
||||
| bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo |
|
||||
| bar.js:12:14:12:17 | iife | iife |
|
||||
| bar.js:12:14:12:17 | iife | IIFE |
|
||||
| bar.js:12:14:12:21 | iife.Foo | IIFE.Foo |
|
||||
| closure.js:8:12:8:15 | goog | goog |
|
||||
| closure.js:8:12:8:19 | goog.net | goog.net |
|
||||
| closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType |
|
||||
| closure.js:9:12:9:14 | net | net |
|
||||
| closure.js:9:12:9:14 | net | goog.net |
|
||||
| closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType |
|
||||
| closure.js:10:12:10:19 | SomeType | goog.net.SomeType |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import javascript
|
||||
|
||||
query string test_hasQualifiedName(JSDocNamedTypeExpr expr) { expr.hasQualifiedName(result) }
|
||||
query string test_hasUnderlyingType(JSDocNamedTypeExpr expr) { expr.hasUnderlyingType(result) }
|
||||
|
||||
@@ -2,13 +2,14 @@ test_isString
|
||||
| tst.js:2:12:2:17 | string |
|
||||
test_isNumber
|
||||
| tst.js:3:12:3:17 | number |
|
||||
test_QualifiedName
|
||||
test_hasUnderlyingType
|
||||
| VarType | tst.js:9:13:9:19 | VarType |
|
||||
| boolean | tst.js:5:14:5:20 | boolean |
|
||||
| foo | tst.js:4:12:4:14 | foo |
|
||||
| foo.bar | tst.js:4:12:4:18 | foo.bar |
|
||||
| foo.bar.baz | tst.js:4:12:4:22 | foo.bar.baz |
|
||||
| number | tst.js:3:12:3:17 | number |
|
||||
| number | tst.js:3:12:3:18 | number? |
|
||||
| string | tst.js:2:12:2:17 | string |
|
||||
test_ParameterType
|
||||
| tst.js:7:12:7:12 | x | tst.js:2:12:2:17 | string |
|
||||
|
||||
@@ -4,7 +4,7 @@ query TypeAnnotation test_isString() { result.isString() }
|
||||
|
||||
query TypeAnnotation test_isNumber() { result.isNumber() }
|
||||
|
||||
query TypeAnnotation test_QualifiedName(string name) { result.hasQualifiedName(name) }
|
||||
query TypeAnnotation test_hasUnderlyingType(string name) { result.hasUnderlyingType(name) }
|
||||
|
||||
query TypeAnnotation test_ParameterType(Parameter p) { result = p.getTypeAnnotation() }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from TypeAnnotation type, string mod, string name
|
||||
where type.hasQualifiedName(mod, name)
|
||||
where type.hasUnderlyingType(mod, name)
|
||||
select type, mod, name
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
| tst.ts:38:3:38:19 | resolveAmbient(x) | x should not resolve to a global |
|
||||
| tst.ts:22:3:22:18 | resolveGlobal(x) | x should resolve to a global variable |
|
||||
| tst.ts:23:3:23:18 | resolveGlobal(y) | y should resolve to a global variable |
|
||||
| tst.ts:24:3:24:18 | resolveGlobal(z) | z should resolve to a global variable |
|
||||
| tst.ts:25:3:25:18 | resolveGlobal(w) | w should resolve to a global variable |
|
||||
| tst.ts:39:3:39:18 | resolveGlobal(y) | y should resolve to a global variable |
|
||||
| tst.ts:40:3:40:18 | resolveGlobal(z) | z should resolve to a global variable |
|
||||
| tst.ts:41:3:41:18 | resolveGlobal(w) | w should resolve to a global variable |
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
| tst.ts:52:3:52:23 | obj.sim ... od(str) | TestInterface.simpleMethod in global scope | no concrete target |
|
||||
| tst.ts:53:3:53:24 | obj.gen ... od(str) | TestInterface.genericMethod in global scope | no concrete target |
|
||||
| tst.ts:54:3:54:24 | obj.gen ... od(num) | TestInterface.genericMethod in global scope | no concrete target |
|
||||
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
|
||||
| tst.ts:52:3:52:23 | obj.sim ... od(str) | TestInterface.simpleMethod in global scope | simpleM ... number; |
|
||||
| tst.ts:53:3:53:24 | obj.gen ... od(str) | TestInterface.genericMethod in global scope | generic ... T): T; |
|
||||
| tst.ts:54:3:54:24 | obj.gen ... od(num) | TestInterface.genericMethod in global scope | generic ... T): T; |
|
||||
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
|
||||
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... number; |
|
||||
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... string; |
|
||||
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
|
||||
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... number; |
|
||||
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... string; |
|
||||
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
|
||||
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... number; |
|
||||
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... string; |
|
||||
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
|
||||
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
|
||||
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
|
||||
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
|
||||
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
|
||||
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
|
||||
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
|
||||
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
|
||||
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
|
||||
| tst.ts:64:3:64:23 | obj.sim ... od(str) | TestClass.simpleMethod in global scope | simpleM ... ength } |
|
||||
| tst.ts:65:3:65:24 | obj.gen ... od(str) | TestClass.genericMethod in global scope | generic ... rn x; } |
|
||||
| tst.ts:66:3:66:24 | obj.gen ... od(num) | TestClass.genericMethod in global scope | generic ... rn x; } |
|
||||
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... number; |
|
||||
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... rn x; } |
|
||||
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... string; |
|
||||
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... number; |
|
||||
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... rn x; } |
|
||||
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... string; |
|
||||
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... T>): T; |
|
||||
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... []): T; |
|
||||
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... null; } |
|
||||
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... T>): T; |
|
||||
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... []): T; |
|
||||
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... null; } |
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
hasQualifiedNameModule
|
||||
| default-import | default | tst.ts:11:9:11:21 | DefaultImport |
|
||||
hasUnderlyingTypeModule
|
||||
| default-import | | tst.ts:11:9:11:21 | DefaultImport |
|
||||
| global | UnresolvedName | tst.ts:12:9:12:22 | UnresolvedName |
|
||||
| import-assign | | tst.ts:10:9:10:11 | asn |
|
||||
| import-assign | Foo | tst.ts:10:9:10:15 | asn.Foo |
|
||||
| named-import | Name1 | tst.ts:7:9:7:13 | Name1 |
|
||||
| named-import | Name1 | tst.ts:13:9:13:13 | Name1 |
|
||||
| named-import | Name1 | tst.ts:13:9:13:21 | Name1<number> |
|
||||
| named-import | Name2 | tst.ts:8:9:8:13 | Name2 |
|
||||
| namespace-import | | tst.ts:9:9:9:17 | namespace |
|
||||
| namespace-import | Foo | tst.ts:9:9:9:21 | namespace.Foo |
|
||||
| tst.ts | ExportedClass | relative.ts:4:8:4:20 | ExportedClass |
|
||||
hasQualifiedNameGlobal
|
||||
hasUnderlyingTypeGlobal
|
||||
| UnresolvedName | tst.ts:12:9:12:22 | UnresolvedName |
|
||||
paramExample
|
||||
| tst.ts:7:5:7:6 | x1 |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import javascript
|
||||
|
||||
query TypeAnnotation hasQualifiedNameModule(string moduleName, string member) {
|
||||
result.hasQualifiedName(moduleName, member)
|
||||
query TypeAnnotation hasUnderlyingTypeModule(string moduleName, string member) {
|
||||
result.hasUnderlyingType(moduleName, member)
|
||||
}
|
||||
|
||||
query TypeAnnotation hasQualifiedNameGlobal(string globalName) {
|
||||
result.hasQualifiedName(globalName)
|
||||
query TypeAnnotation hasUnderlyingTypeGlobal(string globalName) {
|
||||
result.hasUnderlyingType(globalName)
|
||||
}
|
||||
|
||||
query Parameter paramExample() {
|
||||
result.getTypeAnnotation().hasQualifiedName("named-import", "Name1")
|
||||
result.getTypeAnnotation().hasUnderlyingType("named-import", "Name1")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
| tst.ts:8:14:8:16 | arg | Sub in global scope |
|
||||
underlyingTypeNode
|
||||
| foo | | file://:0:0:0:0 | use moduleImport("foo").getMember("exports") |
|
||||
| foo | | file://:0:0:0:0 | use moduleImport("foo").getMember("exports").getMember("") |
|
||||
| foo | | foo.ts:1:8:1:10 | use moduleImport("foo").getMember("exports").getMember("default") |
|
||||
| foo | Bar | foo.ts:3:1:5:1 | use moduleImport("foo").getMember("exports").getMember("Bar").getInstance() |
|
||||
| foo | Bar | foo.ts:3:12:3:12 | use moduleImport("foo").getMember("exports").getMember("Bar").getInstance() |
|
||||
|
||||
32
javascript/ql/test/library-tests/UnderlyingTypes/calls.ts
Normal file
32
javascript/ql/test/library-tests/UnderlyingTypes/calls.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as express from 'express';
|
||||
|
||||
function getRequest(): express.Request { }
|
||||
|
||||
function t1() {
|
||||
getRequest(); // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
declare function getRequestAmbient(): express.Request;
|
||||
|
||||
function t2() {
|
||||
getRequestAmbient(); // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
class C {
|
||||
method(): express.Request { }
|
||||
}
|
||||
|
||||
function t3(c: C) {
|
||||
c.method(); // $ hasUnderlyingType='express'.Request
|
||||
new C().method(); // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function callback(fn: (req: express.Request) => void) { // $ SPURIOUS: hasUnderlyingType='express'.Request // req seems to be a SourceNode
|
||||
}
|
||||
|
||||
function t4() {
|
||||
callback(function (
|
||||
req // $ hasUnderlyingType='express'.Request
|
||||
) { }
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
goog.declareModuleId("closure.es")
|
||||
|
||||
const Bar = goog.require('closure.reexported.Bar');
|
||||
|
||||
export { Bar }
|
||||
@@ -0,0 +1,3 @@
|
||||
goog.module("closure.lib")
|
||||
|
||||
exports.Foo = goog.require('closure.reexported.Foo');
|
||||
@@ -0,0 +1,16 @@
|
||||
goog.module("closure.use")
|
||||
|
||||
const lib = goog.require("closure.lib");
|
||||
const es = goog.require("closure.es");
|
||||
|
||||
/**
|
||||
* @param {lib.Foo} x
|
||||
*/
|
||||
function t1(x) { // $ hasUnderlyingType=closure.reexported.Foo hasUnderlyingType=closure.lib.Foo
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {es.Bar} x
|
||||
*/
|
||||
function t2(x) { // $ hasUnderlyingType=closure.reexported.Bar hasUnderlyingType=closure.es.Bar
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import * as express from 'express';
|
||||
|
||||
interface Options {
|
||||
handle(req: express.Request): void; // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
declare function doSomething(options: Options);
|
||||
|
||||
function t1() {
|
||||
doSomething({
|
||||
handle(req) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function t2(callback: ((opts: Options) => void) | undefined) {
|
||||
callback({
|
||||
handle(req) { } // $ hasUnderlyingType='express'.Request
|
||||
})
|
||||
callback!({
|
||||
handle(req) { } // $ hasUnderlyingType='express'.Request
|
||||
})
|
||||
}
|
||||
|
||||
function t3(): Options {
|
||||
return {
|
||||
handle(req) { } // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
}
|
||||
|
||||
function t4(): Options[] {
|
||||
return [
|
||||
{
|
||||
handle(req) { } // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
async function t5(): Promise<Options> {
|
||||
return {
|
||||
handle(req) { // $ hasUnderlyingType='express'.Request
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from 'express';
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Request, Response } from './expressBulkExport';
|
||||
|
||||
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t2(res: Response) { // $ hasUnderlyingType='express'.Response
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import E = require('express');
|
||||
export = E;
|
||||
@@ -0,0 +1,4 @@
|
||||
import { Request } from "./expressExportAssign";
|
||||
|
||||
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Express = require('express');
|
||||
namespace Wrapper {
|
||||
export import E = Express;
|
||||
}
|
||||
export = Wrapper;
|
||||
@@ -0,0 +1,4 @@
|
||||
import { E } from "./expressExportAssignWrapper";
|
||||
|
||||
function t1(req: E.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Request } from 'express';
|
||||
export { Response as R } from 'express';
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Request, Response, R } from './expressSelectiveExport';
|
||||
|
||||
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t2(res: Response) { // none, not exported
|
||||
}
|
||||
|
||||
function t3(res: R) { // $ hasUnderlyingType='express'.Response
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * as wrapper from 'express';
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Request, Response, wrapper } from './expressWrapperExport';
|
||||
import * as w from './expressWrapperExport';
|
||||
|
||||
function t1(req: Request) { // none
|
||||
}
|
||||
|
||||
function t2(res: Response) { // none
|
||||
}
|
||||
|
||||
function t3(req: wrapper.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t4(res: wrapper.Response) { // $ hasUnderlyingType='express'.Response
|
||||
}
|
||||
|
||||
function t5(req: w.wrapper.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t6(res: w.wrapper.Response) { // $ hasUnderlyingType='express'.Response
|
||||
}
|
||||
|
||||
function t7(req: w.Request) { // none
|
||||
}
|
||||
|
||||
function t8(res: w.Response) { // none
|
||||
}
|
||||
|
||||
function t9(e: typeof w.wrapper) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
46
javascript/ql/test/library-tests/UnderlyingTypes/generics.ts
Normal file
46
javascript/ql/test/library-tests/UnderlyingTypes/generics.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import * as express from 'express';
|
||||
|
||||
type Box1<T> = {
|
||||
value: T;
|
||||
other: string;
|
||||
};
|
||||
function t1(b: Box1<express.Request>) {
|
||||
b.value; // $ MISSING: hasUnderlyingType='express'.Request
|
||||
b.other;
|
||||
}
|
||||
|
||||
interface Box2<T> {
|
||||
value: T;
|
||||
other: string;
|
||||
}
|
||||
function t2(b: Box2<express.Request>) {
|
||||
b.value; // $ MISSING: hasUnderlyingType='express'.Request
|
||||
b.other;
|
||||
}
|
||||
|
||||
class Box3<T> {
|
||||
value: T;
|
||||
other: string;
|
||||
}
|
||||
function t3(b: Box3<express.Request>) {
|
||||
b.value; // $ MISSING: hasUnderlyingType='express'.Request
|
||||
b.other;
|
||||
}
|
||||
|
||||
abstract class Box4<T> {
|
||||
abstract getValue(): T;
|
||||
abstract getOther(): string;
|
||||
}
|
||||
function t4(b: Box4<express.Request>) {
|
||||
b.getValue(); // $ MISSING: hasUnderlyingType='express'.Request
|
||||
b.getOther();
|
||||
}
|
||||
|
||||
type Box5<T> = {
|
||||
value: T & { blah: string };
|
||||
other: string;
|
||||
};
|
||||
function t5(b: Box5<express.Request>) {
|
||||
b.value; // $ MISSING: hasUnderlyingType='express'.Request
|
||||
b.other;
|
||||
}
|
||||
10
javascript/ql/test/library-tests/UnderlyingTypes/globals.ts
Normal file
10
javascript/ql/test/library-tests/UnderlyingTypes/globals.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
function t1(el: HTMLElement) { } // $ hasUnderlyingType=HTMLElement
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} el
|
||||
*/
|
||||
function t2(el) { // $ hasUnderlyingType=HTMLInputElement
|
||||
}
|
||||
|
||||
function t3(req: Express.Request) { // $ hasUnderlyingType=Express.Request
|
||||
}
|
||||
14
javascript/ql/test/library-tests/UnderlyingTypes/jsdoc.js
Normal file
14
javascript/ql/test/library-tests/UnderlyingTypes/jsdoc.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as e from 'express';
|
||||
import { Response } from 'express';
|
||||
|
||||
/**
|
||||
* @param {e.Request} req
|
||||
*/
|
||||
function t1(req) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Response} res
|
||||
*/
|
||||
function t2(res) { // $ hasUnderlyingType='express'.Response
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { Request } from 'express';
|
||||
|
||||
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Express = require('express');
|
||||
|
||||
namespace A {
|
||||
export import E = Express;
|
||||
}
|
||||
namespace B {
|
||||
export import Q = A
|
||||
}
|
||||
namespace C {
|
||||
import E = Express;
|
||||
export const A = E;
|
||||
}
|
||||
|
||||
function t1(x: A.E.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t2(x: B.Q.E.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t3(x: typeof Express) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
|
||||
function t4(x: typeof A.E) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
|
||||
function t5(x: typeof C.A) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as express from 'express';
|
||||
|
||||
function t1(e: typeof express) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
|
||||
function t2(req: express.Request) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
function t3(req: Request) { // $ hasUnderlyingType=Request // not in scope, refers to a global
|
||||
}
|
||||
|
||||
type E = typeof express;
|
||||
|
||||
function t4(e: E) { // $ hasUnderlyingType='express'
|
||||
}
|
||||
16
javascript/ql/test/library-tests/UnderlyingTypes/props.ts
Normal file
16
javascript/ql/test/library-tests/UnderlyingTypes/props.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as express from 'express';
|
||||
|
||||
interface Foo {
|
||||
req: express.Request;
|
||||
e: typeof express;
|
||||
}
|
||||
|
||||
function t1(f: Foo) {
|
||||
f.req; // $ hasUnderlyingType='express'.Request
|
||||
f.e; // $ hasUnderlyingType='express'
|
||||
|
||||
const {
|
||||
req, // $ hasUnderlyingType='express'.Request
|
||||
e // $ hasUnderlyingType='express'
|
||||
} = f;
|
||||
}
|
||||
20
javascript/ql/test/library-tests/UnderlyingTypes/subtype.ts
Normal file
20
javascript/ql/test/library-tests/UnderlyingTypes/subtype.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as express from 'express';
|
||||
|
||||
interface MyRequest extends express.Request {
|
||||
|
||||
}
|
||||
|
||||
function t1(req: MyRequest) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
class MyRequestClass extends express.Request {
|
||||
}
|
||||
|
||||
function t2(req: MyRequestClass) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
|
||||
class MyRequestClass2 implements express.Request {
|
||||
}
|
||||
|
||||
function t3(req: MyRequestClass2) { // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
| calls.ts:6:5:6:16 | getRequest() | 'express'.Request |
|
||||
| calls.ts:12:5:12:23 | getRequestAmbient() | 'express'.Request |
|
||||
| calls.ts:20:5:20:14 | c.method() | 'express'.Request |
|
||||
| calls.ts:21:5:21:20 | new C().method() | 'express'.Request |
|
||||
| calls.ts:24:24:24:26 | req | 'express'.Request |
|
||||
| calls.ts:29:9:29:11 | req | 'express'.Request |
|
||||
| closure.use.js:9:13:9:13 | x | closure.lib.Foo |
|
||||
| closure.use.js:9:13:9:13 | x | closure.reexported.Foo |
|
||||
| closure.use.js:15:13:15:13 | x | closure.es.Bar |
|
||||
| closure.use.js:15:13:15:13 | x | closure.reexported.Bar |
|
||||
| contextualTypes.ts:4:12:4:14 | req | 'express'.Request |
|
||||
| contextualTypes.ts:11:16:11:18 | req | 'express'.Request |
|
||||
| contextualTypes.ts:18:16:18:18 | req | 'express'.Request |
|
||||
| contextualTypes.ts:21:16:21:18 | req | 'express'.Request |
|
||||
| contextualTypes.ts:27:16:27:18 | req | 'express'.Request |
|
||||
| contextualTypes.ts:34:20:34:22 | req | 'express'.Request |
|
||||
| contextualTypes.ts:41:16:41:18 | req | 'express'.Request |
|
||||
| expressBulkExport.use.ts:3:13:3:15 | req | 'express'.Request |
|
||||
| expressBulkExport.use.ts:6:13:6:15 | res | 'express'.Response |
|
||||
| expressExportAssign.use.ts:3:13:3:15 | req | 'express'.Request |
|
||||
| expressExportAssignWrapper.use.ts:3:13:3:15 | req | 'express'.Request |
|
||||
| expressSelectiveExport.use.ts:3:13:3:15 | req | 'express'.Request |
|
||||
| expressSelectiveExport.use.ts:9:13:9:15 | res | 'express'.Response |
|
||||
| expressWrapperExport.use.ts:10:13:10:15 | req | 'express'.Request |
|
||||
| expressWrapperExport.use.ts:13:13:13:15 | res | 'express'.Response |
|
||||
| expressWrapperExport.use.ts:16:13:16:15 | req | 'express'.Request |
|
||||
| expressWrapperExport.use.ts:19:13:19:15 | res | 'express'.Response |
|
||||
| expressWrapperExport.use.ts:28:13:28:13 | e | 'express' |
|
||||
| globals.ts:1:13:1:14 | el | HTMLElement |
|
||||
| globals.ts:6:13:6:14 | el | HTMLInputElement |
|
||||
| globals.ts:9:13:9:15 | req | Express.Request |
|
||||
| jsdoc.js:7:13:7:15 | req | 'express'.Request |
|
||||
| jsdoc.js:13:13:13:15 | res | 'express'.Response |
|
||||
| namedImport.ts:3:13:3:15 | req | 'express'.Request |
|
||||
| namespaceDecls.ts:14:13:14:13 | x | 'express'.Request |
|
||||
| namespaceDecls.ts:17:13:17:13 | x | 'express'.Request |
|
||||
| namespaceDecls.ts:20:13:20:13 | x | 'express' |
|
||||
| namespaceDecls.ts:23:13:23:13 | x | 'express' |
|
||||
| namespaceDecls.ts:26:13:26:13 | x | 'express' |
|
||||
| namespaceImport.ts:3:13:3:13 | e | 'express' |
|
||||
| namespaceImport.ts:6:13:6:15 | req | 'express'.Request |
|
||||
| namespaceImport.ts:9:13:9:15 | req | Request |
|
||||
| namespaceImport.ts:14:13:14:13 | e | 'express' |
|
||||
| props.ts:9:5:9:9 | f.req | 'express'.Request |
|
||||
| props.ts:10:5:10:7 | f.e | 'express' |
|
||||
| props.ts:13:9:13:11 | req | 'express'.Request |
|
||||
| props.ts:14:9:14:9 | e | 'express' |
|
||||
| subtype.ts:7:13:7:15 | req | 'express'.Request |
|
||||
| subtype.ts:13:13:13:15 | req | 'express'.Request |
|
||||
| subtype.ts:19:13:19:15 | req | 'express'.Request |
|
||||
| typeCast.ts:4:16:4:35 | e as express.Request | 'express'.Request |
|
||||
| typeCast.ts:5:16:5:33 | <express.Request>e | 'express'.Request |
|
||||
| typeCast.ts:6:16:6:42 | e satis ... Request | 'express'.Request |
|
||||
| varAssignment.ts:4:9:4:11 | req | 'express'.Request |
|
||||
15
javascript/ql/test/library-tests/UnderlyingTypes/test.ql
Normal file
15
javascript/ql/test/library-tests/UnderlyingTypes/test.ql
Normal file
@@ -0,0 +1,15 @@
|
||||
import javascript
|
||||
|
||||
bindingset[x, y]
|
||||
private string join(string x, string y) {
|
||||
if x = "" or y = "" then result = x + y else result = x + "." + y
|
||||
}
|
||||
|
||||
query predicate hasUnderlyingType(DataFlow::SourceNode node, string value) {
|
||||
node.hasUnderlyingType(value)
|
||||
or
|
||||
exists(string mod, string name |
|
||||
node.hasUnderlyingType(mod, name) and
|
||||
value = join("'" + mod + "'", name)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
query: test.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"include": ["."]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as express from 'express';
|
||||
|
||||
function t1(e) {
|
||||
var req1 = e as express.Request; // $ hasUnderlyingType='express'.Request
|
||||
var req2 = <express.Request>e; // $ hasUnderlyingType='express'.Request
|
||||
var req3 = e satisfies express.Request; // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as express from 'express';
|
||||
|
||||
function t1(e) {
|
||||
var req: express.Request = e; // $ hasUnderlyingType='express'.Request
|
||||
}
|
||||
@@ -71,6 +71,9 @@ responseSendArgument
|
||||
| local/customPipe.ts:37:16:37:31 | '' + unsanitized |
|
||||
| local/customPipe.ts:42:16:42:31 | '' + unsanitized |
|
||||
| local/customPipe.ts:48:16:48:31 | '' + unsanitized |
|
||||
| local/routes.ts:7:12:7:16 | 'foo' |
|
||||
| local/routes.ts:12:12:12:16 | 'foo' |
|
||||
| local/routes.ts:17:12:17:16 | 'foo' |
|
||||
| local/routes.ts:32:31:32:31 | x |
|
||||
| local/routes.ts:33:31:33:38 | queryObj |
|
||||
| local/routes.ts:34:31:34:34 | name |
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
| dragAndDrop.ts:73:29:73:39 | droppedHtml | dragAndDrop.ts:71:27:71:61 | e.dataT ... /html') | dragAndDrop.ts:73:29:73:39 | droppedHtml | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:71:27:71:61 | e.dataT ... /html') | user-provided value |
|
||||
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | Cross-site scripting vulnerability due to $@. | event-handler-receiver.js:2:49:2:61 | location.href | user-provided value |
|
||||
| express.js:6:15:6:33 | req.param("wobble") | express.js:6:15:6:33 | req.param("wobble") | express.js:6:15:6:33 | req.param("wobble") | Cross-site scripting vulnerability due to $@. | express.js:6:15:6:33 | req.param("wobble") | user-provided value |
|
||||
| jquery-declare-any.ts:6:7:6:17 | window.name | jquery-declare-any.ts:6:7:6:17 | window.name | jquery-declare-any.ts:6:7:6:17 | window.name | Cross-site scripting vulnerability due to $@. | jquery-declare-any.ts:6:7:6:17 | window.name | user-provided value |
|
||||
| jquery-declare-type.ts:6:7:6:17 | window.name | jquery-declare-type.ts:6:7:6:17 | window.name | jquery-declare-type.ts:6:7:6:17 | window.name | Cross-site scripting vulnerability due to $@. | jquery-declare-type.ts:6:7:6:17 | window.name | user-provided value |
|
||||
| jquery.js:7:5:7:34 | "<div i ... + "\\">" | jquery.js:2:17:2:40 | documen ... .search | jquery.js:7:5:7:34 | "<div i ... + "\\">" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value |
|
||||
| jquery.js:8:18:8:34 | "XSS: " + tainted | jquery.js:2:17:2:40 | documen ... .search | jquery.js:8:18:8:34 | "XSS: " + tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value |
|
||||
| jquery.js:10:5:10:40 | "<b>" + ... "</b>" | jquery.js:10:13:10:20 | location | jquery.js:10:5:10:40 | "<b>" + ... "</b>" | Cross-site scripting vulnerability due to $@. | jquery.js:10:13:10:20 | location | user-provided value |
|
||||
@@ -954,6 +956,8 @@ nodes
|
||||
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | semmle.label | '<h2><a ... ></h2>' |
|
||||
| event-handler-receiver.js:2:49:2:61 | location.href | semmle.label | location.href |
|
||||
| express.js:6:15:6:33 | req.param("wobble") | semmle.label | req.param("wobble") |
|
||||
| jquery-declare-any.ts:6:7:6:17 | window.name | semmle.label | window.name |
|
||||
| jquery-declare-type.ts:6:7:6:17 | window.name | semmle.label | window.name |
|
||||
| jquery.js:2:7:2:40 | tainted | semmle.label | tainted |
|
||||
| jquery.js:2:17:2:40 | documen ... .search | semmle.label | documen ... .search |
|
||||
| jquery.js:4:5:4:11 | tainted | semmle.label | tainted |
|
||||
|
||||
@@ -182,6 +182,8 @@ nodes
|
||||
| hana.js:85:35:85:54 | tableRows[0].comment | semmle.label | tableRows[0].comment |
|
||||
| hana.js:90:33:90:34 | rs | semmle.label | rs |
|
||||
| hana.js:90:33:90:45 | rs[0].comment | semmle.label | rs[0].comment |
|
||||
| jquery-declare-any.ts:6:7:6:17 | window.name | semmle.label | window.name |
|
||||
| jquery-declare-type.ts:6:7:6:17 | window.name | semmle.label | window.name |
|
||||
| jquery.js:2:7:2:40 | tainted | semmle.label | tainted |
|
||||
| jquery.js:2:17:2:40 | documen ... .search | semmle.label | documen ... .search |
|
||||
| jquery.js:4:5:4:11 | tainted | semmle.label | tainted |
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import 'dummy';
|
||||
|
||||
declare var $: any;
|
||||
|
||||
function t() {
|
||||
$(window.name); // $ Alert
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import 'dummy';
|
||||
|
||||
declare var $: JQueryStatic;
|
||||
|
||||
function t() {
|
||||
$(window.name); // $ Alert
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
| main.js:111:37:111:37 | x | main.js:98:43:98:43 | x | main.js:111:37:111:37 | x | This markdown rendering which depends on $@ might later allow $@. | main.js:98:43:98:43 | x | library input | main.js:112:24:112:26 | svg | cross-site scripting |
|
||||
| main.js:117:34:117:34 | s | main.js:116:47:116:47 | s | main.js:117:34:117:34 | s | This markdown rendering which depends on $@ might later allow $@. | main.js:116:47:116:47 | s | library input | main.js:118:53:118:56 | html | cross-site scripting |
|
||||
| typed.ts:2:29:2:29 | s | typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s | This HTML construction which depends on $@ might later allow $@. | typed.ts:1:39:1:39 | s | library input | typed.ts:3:31:3:34 | html | cross-site scripting |
|
||||
| typed.ts:8:40:8:40 | s | typed.ts:6:43:6:43 | s | typed.ts:8:40:8:40 | s | This HTML construction which depends on $@ might later allow $@. | typed.ts:6:43:6:43 | s | library input | typed.ts:8:29:8:52 | "<span> ... /span>" | cross-site scripting |
|
||||
edges
|
||||
| jquery-plugin.js:11:27:11:31 | stuff | jquery-plugin.js:14:31:14:35 | stuff | provenance | |
|
||||
| jquery-plugin.js:11:34:11:40 | options | jquery-plugin.js:12:31:12:37 | options | provenance | |
|
||||
@@ -69,7 +68,6 @@ edges
|
||||
| main.js:98:43:98:43 | x | main.js:111:37:111:37 | x | provenance | |
|
||||
| main.js:116:47:116:47 | s | main.js:117:34:117:34 | s | provenance | |
|
||||
| typed.ts:1:39:1:39 | s | typed.ts:2:29:2:29 | s | provenance | |
|
||||
| typed.ts:6:43:6:43 | s | typed.ts:8:40:8:40 | s | provenance | |
|
||||
nodes
|
||||
| jquery-plugin.js:11:27:11:31 | stuff | semmle.label | stuff |
|
||||
| jquery-plugin.js:11:34:11:40 | options | semmle.label | options |
|
||||
@@ -128,6 +126,4 @@ nodes
|
||||
| main.js:117:34:117:34 | s | semmle.label | s |
|
||||
| typed.ts:1:39:1:39 | s | semmle.label | s |
|
||||
| typed.ts:2:29:2:29 | s | semmle.label | s |
|
||||
| typed.ts:6:43:6:43 | s | semmle.label | s |
|
||||
| typed.ts:8:40:8:40 | s | semmle.label | s |
|
||||
subpaths
|
||||
|
||||
@@ -3,9 +3,9 @@ export function basicHtmlConstruction(s: string) { // $ Source
|
||||
document.body.innerHTML = html;
|
||||
}
|
||||
|
||||
export function insertIntoCreatedDocument(s: string) { // $ Source
|
||||
export function insertIntoCreatedDocument(s: string) {
|
||||
const newDoc = document.implementation.createHTMLDocument("");
|
||||
newDoc.body.innerHTML = "<span>" + s + "</span>"; // $ SPURIOUS: Alert - inserted into document disconnected from the main DOM.
|
||||
newDoc.body.innerHTML = "<span>" + s + "</span>"; // OK - inserted into document disconnected from the main DOM.
|
||||
}
|
||||
|
||||
export function id(s: string) {
|
||||
@@ -17,4 +17,3 @@ export function notVulnerable() {
|
||||
const html = "<span>" + s + "</span>";
|
||||
document.body.innerHTML = html;
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
| b.js:3:3:3:3 | x | b.js:2:7:2:7 | x | V |
|
||||
| b.js:7:1:7:1 | f | b.js:1:1:5:1 | functio ... ar x;\\n} | M |
|
||||
| b.js:8:1:8:1 | g | a.js:2:1:2:15 | function g() {} | M |
|
||||
| b.js:7:1:7:1 | f | b.js:1:10:1:10 | f | M |
|
||||
| b.js:8:1:8:1 | g | a.js:2:10:2:10 | g | M |
|
||||
| client.ts:1:22:1:30 | "./tslib" | tslib.ts:1:1:10:0 | <toplevel> | I |
|
||||
| client.ts:7:19:7:19 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
|
||||
| client.ts:8:10:8:10 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
|
||||
| client.ts:9:16:9:16 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
|
||||
| client.ts:10:16:10:16 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
|
||||
| client.ts:13:25:13:25 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
|
||||
| client.ts:13:35:13:35 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
|
||||
| client.ts:13:47:13:47 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
|
||||
| client.ts:7:19:7:19 | C | tslib.ts:1:14:1:14 | C | T |
|
||||
| client.ts:8:10:8:10 | C | client.ts:3:7:3:7 | C | T |
|
||||
| client.ts:9:16:9:16 | C | client.ts:3:7:3:7 | C | T |
|
||||
| client.ts:10:16:10:16 | C | tslib.ts:6:16:6:16 | C | T |
|
||||
| client.ts:13:25:13:25 | C | client.ts:3:7:3:7 | C | T |
|
||||
| client.ts:13:35:13:35 | C | tslib.ts:1:14:1:14 | C | T |
|
||||
| client.ts:13:47:13:47 | C | tslib.ts:6:16:6:16 | C | T |
|
||||
| client.ts:14:3:14:3 | x | client.ts:13:22:13:22 | x | V |
|
||||
| client.ts:14:5:14:5 | m | client.ts:4:3:4:8 | m() {} | M |
|
||||
| client.ts:14:5:14:5 | m | client.ts:4:3:4:3 | m | M |
|
||||
| client.ts:15:3:15:3 | y | client.ts:13:28:13:28 | y | V |
|
||||
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:8 | m() {} | M |
|
||||
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:3 | m | M |
|
||||
| client.ts:16:3:16:3 | z | client.ts:13:38:13:38 | z | V |
|
||||
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:10 | m() {} | M |
|
||||
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:5 | m | M |
|
||||
| d.js:1:17:1:21 | './c' | c.js:1:1:1:20 | <toplevel> | I |
|
||||
| d.js:10:1:10:1 | A | d.js:7:1:9:1 | functio ... = 42;\\n} | V |
|
||||
| d.js:16:19:16:23 | Super | d.js:12:1:14:1 | class S ... () {}\\n} | V |
|
||||
| d.js:10:1:10:1 | A | d.js:7:10:7:10 | A | V |
|
||||
| d.js:16:19:16:23 | Super | d.js:12:7:12:11 | Super | V |
|
||||
| d.js:16:25:16:24 | args | d.js:16:25:16:24 | args | V |
|
||||
| d.js:20:1:20:1 | o | d.js:3:9:5:1 | {\\n f: ... () {}\\n} | V |
|
||||
| d.js:20:3:20:3 | f | d.js:4:3:4:18 | f: function() {} | M |
|
||||
| d.js:22:13:22:13 | A | d.js:7:1:9:1 | functio ... = 42;\\n} | M |
|
||||
| d.js:22:13:22:13 | A | d.js:7:10:7:10 | A | M |
|
||||
| d.js:23:1:23:1 | a | d.js:22:5:22:5 | a | V |
|
||||
| d.js:23:3:23:3 | x | d.js:8:3:8:8 | this.x | M |
|
||||
| d.js:24:1:24:1 | a | d.js:22:5:22:5 | a | V |
|
||||
| d.js:24:3:24:3 | g | d.js:10:1:10:13 | A.prototype.g | M |
|
||||
| d.js:26:13:26:15 | Sub | d.js:16:1:18:1 | class S ... () {}\\n} | M |
|
||||
| d.js:26:13:26:15 | Sub | d.js:16:7:16:9 | Sub | M |
|
||||
| d.js:27:1:27:1 | x | d.js:26:5:26:5 | x | V |
|
||||
| d.js:27:3:27:3 | m | d.js:13:3:13:3 | m | M |
|
||||
| d.js:28:1:28:1 | x | d.js:26:5:26:5 | x | V |
|
||||
| d.js:28:3:28:3 | n | d.js:17:3:17:3 | n | M |
|
||||
| tst.js:1:19:1:23 | './m' | m.js:1:1:2:0 | <toplevel> | I |
|
||||
| tst.js:3:5:3:5 | A | m.js:1:8:1:17 | class A {} | M |
|
||||
| tst.js:3:5:3:5 | A | m.js:1:14:1:14 | A | M |
|
||||
| tst.js:5:15:5:19 | './m' | m.js:1:1:2:0 | <toplevel> | I |
|
||||
|
||||
Reference in New Issue
Block a user