diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index e7306e77e016..43e70160fe8f 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -426,7 +426,6 @@ public Void visit(Identifier nd, Void v) { // 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 Void visit(FunctionDeclaration nd, Void v) { @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 Void visit(EnhancedForStatement nd, Void v) { @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 Void visit(ClassBody nd, Void c) { @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; } diff --git a/javascript/extractor/tests/ts/output/trap/conditionalTypes.ts.trap b/javascript/extractor/tests/ts/output/trap/conditionalTypes.ts.trap index 0751d283e6cc..2a1c0efbd441 100644 --- a/javascript/extractor/tests/ts/output/trap/conditionalTypes.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/conditionalTypes.ts.trap @@ -8434,1316 +8434,1316 @@ namespacedecl(#22807,#22182) scopes(#22808,9) scopenodes(#22805,#22808) scopenesting(#22808,#20000) -#22809=@"local_type_name;{Unpacked};{#22808}" -local_type_names(#22809,"Unpacked",#22808) -#22810=@"local_type_name;{T0};{#22808}" -local_type_names(#22810,"T0",#22808) -#22811=@"local_type_name;{T1};{#22808}" -local_type_names(#22811,"T1",#22808) -#22812=@"local_type_name;{T2};{#22808}" -local_type_names(#22812,"T2",#22808) -#22813=@"local_type_name;{T3};{#22808}" -local_type_names(#22813,"T3",#22808) -#22814=@"local_type_name;{T4};{#22808}" -local_type_names(#22814,"T4",#22808) -#22815=@"local_type_name;{T5};{#22808}" -local_type_names(#22815,"T5",#22808) -#22816=@"local_type_name;{Foo};{#22808}" -local_type_names(#22816,"Foo",#22808) -#22817=@"local_type_name;{T10};{#22808}" -local_type_names(#22817,"T10",#22808) -#22818=@"local_type_name;{T11};{#22808}" -local_type_names(#22818,"T11",#22808) -#22819=@"local_type_name;{Bar};{#22808}" -local_type_names(#22819,"Bar",#22808) -#22820=@"local_type_name;{T20};{#22808}" -local_type_names(#22820,"T20",#22808) -#22821=@"local_type_name;{T21};{#22808}" -local_type_names(#22821,"T21",#22808) -#22822=@"local_type_name;{T30};{#22808}" -local_type_names(#22822,"T30",#22808) -#22823=@"local_type_name;{AnyFunction};{#22808}" -local_type_names(#22823,"AnyFunction",#22808) -#22824=@"local_type_name;{ReturnType};{#22808}" -local_type_names(#22824,"ReturnType",#22808) -#22825=* -stmts(#22825,35,#22805,0,"type Un ... \n T;") -#22826=@"loc,{#10000},73,3,77,6" -locations_default(#22826,#10000,73,3,77,6) -hasLocation(#22825,#22826) -stmt_containers(#22825,#22805) -#22827=* -typeexprs(#22827,1,#22825,0,"Unpacked") -hasLocation(#22827,#21482) -enclosing_stmt(#22827,#22825) -expr_containers(#22827,#22805) -literals("Unpacked","Unpacked",#22827) -typedecl(#22827,#22809) +#22809=@"var;{foo};{#22808}" +variables(#22809,"foo",#22808) +#22810=@"local_type_name;{Unpacked};{#22808}" +local_type_names(#22810,"Unpacked",#22808) +#22811=@"local_type_name;{T0};{#22808}" +local_type_names(#22811,"T0",#22808) +#22812=@"local_type_name;{T1};{#22808}" +local_type_names(#22812,"T1",#22808) +#22813=@"local_type_name;{T2};{#22808}" +local_type_names(#22813,"T2",#22808) +#22814=@"local_type_name;{T3};{#22808}" +local_type_names(#22814,"T3",#22808) +#22815=@"local_type_name;{T4};{#22808}" +local_type_names(#22815,"T4",#22808) +#22816=@"local_type_name;{T5};{#22808}" +local_type_names(#22816,"T5",#22808) +#22817=@"local_type_name;{Foo};{#22808}" +local_type_names(#22817,"Foo",#22808) +#22818=@"local_type_name;{T10};{#22808}" +local_type_names(#22818,"T10",#22808) +#22819=@"local_type_name;{T11};{#22808}" +local_type_names(#22819,"T11",#22808) +#22820=@"local_type_name;{Bar};{#22808}" +local_type_names(#22820,"Bar",#22808) +#22821=@"local_type_name;{T20};{#22808}" +local_type_names(#22821,"T20",#22808) +#22822=@"local_type_name;{T21};{#22808}" +local_type_names(#22822,"T21",#22808) +#22823=@"local_type_name;{T30};{#22808}" +local_type_names(#22823,"T30",#22808) +#22824=@"local_type_name;{AnyFunction};{#22808}" +local_type_names(#22824,"AnyFunction",#22808) +#22825=@"local_type_name;{ReturnType};{#22808}" +local_type_names(#22825,"ReturnType",#22808) +#22826=* +stmts(#22826,35,#22805,0,"type Un ... \n T;") +#22827=@"loc,{#10000},73,3,77,6" +locations_default(#22827,#10000,73,3,77,6) +hasLocation(#22826,#22827) +stmt_containers(#22826,#22805) #22828=* -scopes(#22828,12) -scopenodes(#22825,#22828) -scopenesting(#22828,#22808) -#22829=@"local_type_name;{T};{#22828}" -local_type_names(#22829,"T",#22828) -#22830=* -typeexprs(#22830,22,#22825,2,"T") -hasLocation(#22830,#21486) -enclosing_stmt(#22830,#22825) -expr_containers(#22830,#22805) +typeexprs(#22828,1,#22826,0,"Unpacked") +hasLocation(#22828,#21482) +enclosing_stmt(#22828,#22826) +expr_containers(#22828,#22805) +literals("Unpacked","Unpacked",#22828) +typedecl(#22828,#22810) +#22829=* +scopes(#22829,12) +scopenodes(#22826,#22829) +scopenesting(#22829,#22808) +#22830=@"local_type_name;{T};{#22829}" +local_type_names(#22830,"T",#22829) #22831=* -typeexprs(#22831,1,#22830,0,"T") +typeexprs(#22831,22,#22826,2,"T") hasLocation(#22831,#21486) -enclosing_stmt(#22831,#22825) +enclosing_stmt(#22831,#22826) expr_containers(#22831,#22805) -literals("T","T",#22831) -typedecl(#22831,#22829) #22832=* -typeexprs(#22832,28,#22825,1,"T exten ... :\n T") -#22833=@"loc,{#10000},74,5,77,5" -locations_default(#22833,#10000,74,5,77,5) -hasLocation(#22832,#22833) -enclosing_stmt(#22832,#22825) +typeexprs(#22832,1,#22831,0,"T") +hasLocation(#22832,#21486) +enclosing_stmt(#22832,#22826) expr_containers(#22832,#22805) -#22834=* -typeexprs(#22834,0,#22832,0,"T") -hasLocation(#22834,#21492) -enclosing_stmt(#22834,#22825) -expr_containers(#22834,#22805) -literals("T","T",#22834) -typebind(#22834,#22829) +literals("T","T",#22832) +typedecl(#22832,#22830) +#22833=* +typeexprs(#22833,28,#22826,1,"T exten ... :\n T") +#22834=@"loc,{#10000},74,5,77,5" +locations_default(#22834,#10000,74,5,77,5) +hasLocation(#22833,#22834) +enclosing_stmt(#22833,#22826) +expr_containers(#22833,#22805) #22835=* -scopes(#22835,16) -scopenodes(#22832,#22835) -scopenesting(#22835,#22828) -#22836=@"local_type_name;{U};{#22835}" -local_type_names(#22836,"U",#22835) -#22837=* -typeexprs(#22837,6,#22832,1,"(infer U)[]") -#22838=@"loc,{#10000},74,15,74,25" -locations_default(#22838,#10000,74,15,74,25) -hasLocation(#22837,#22838) -enclosing_stmt(#22837,#22825) -expr_containers(#22837,#22805) -#22839=* -typeexprs(#22839,10,#22837,0,"(infer U)") -#22840=@"loc,{#10000},74,15,74,23" -locations_default(#22840,#10000,74,15,74,23) -hasLocation(#22839,#22840) -enclosing_stmt(#22839,#22825) -expr_containers(#22839,#22805) -#22841=* -typeexprs(#22841,29,#22839,0,"infer U") -#22842=@"loc,{#10000},74,16,74,22" -locations_default(#22842,#10000,74,16,74,22) -hasLocation(#22841,#22842) -enclosing_stmt(#22841,#22825) -expr_containers(#22841,#22805) -#22843=* -typeexprs(#22843,22,#22841,0,"U") -hasLocation(#22843,#21500) -enclosing_stmt(#22843,#22825) -expr_containers(#22843,#22805) +typeexprs(#22835,0,#22833,0,"T") +hasLocation(#22835,#21492) +enclosing_stmt(#22835,#22826) +expr_containers(#22835,#22805) +literals("T","T",#22835) +typebind(#22835,#22830) +#22836=* +scopes(#22836,16) +scopenodes(#22833,#22836) +scopenesting(#22836,#22829) +#22837=@"local_type_name;{U};{#22836}" +local_type_names(#22837,"U",#22836) +#22838=* +typeexprs(#22838,6,#22833,1,"(infer U)[]") +#22839=@"loc,{#10000},74,15,74,25" +locations_default(#22839,#10000,74,15,74,25) +hasLocation(#22838,#22839) +enclosing_stmt(#22838,#22826) +expr_containers(#22838,#22805) +#22840=* +typeexprs(#22840,10,#22838,0,"(infer U)") +#22841=@"loc,{#10000},74,15,74,23" +locations_default(#22841,#10000,74,15,74,23) +hasLocation(#22840,#22841) +enclosing_stmt(#22840,#22826) +expr_containers(#22840,#22805) +#22842=* +typeexprs(#22842,29,#22840,0,"infer U") +#22843=@"loc,{#10000},74,16,74,22" +locations_default(#22843,#10000,74,16,74,22) +hasLocation(#22842,#22843) +enclosing_stmt(#22842,#22826) +expr_containers(#22842,#22805) #22844=* -typeexprs(#22844,1,#22843,0,"U") +typeexprs(#22844,22,#22842,0,"U") hasLocation(#22844,#21500) -enclosing_stmt(#22844,#22825) +enclosing_stmt(#22844,#22826) expr_containers(#22844,#22805) -literals("U","U",#22844) -typedecl(#22844,#22836) #22845=* -typeexprs(#22845,0,#22832,2,"U") -hasLocation(#22845,#21510) -enclosing_stmt(#22845,#22825) +typeexprs(#22845,1,#22844,0,"U") +hasLocation(#22845,#21500) +enclosing_stmt(#22845,#22826) expr_containers(#22845,#22805) literals("U","U",#22845) -typebind(#22845,#22836) +typedecl(#22845,#22837) #22846=* -typeexprs(#22846,28,#22832,3,"T exten ... :\n T") -#22847=@"loc,{#10000},75,5,77,5" -locations_default(#22847,#10000,75,5,77,5) -hasLocation(#22846,#22847) -enclosing_stmt(#22846,#22825) +typeexprs(#22846,0,#22833,2,"U") +hasLocation(#22846,#21510) +enclosing_stmt(#22846,#22826) expr_containers(#22846,#22805) -#22848=* -typeexprs(#22848,0,#22846,0,"T") -hasLocation(#22848,#21514) -enclosing_stmt(#22848,#22825) -expr_containers(#22848,#22805) -literals("T","T",#22848) -typebind(#22848,#22829) +literals("U","U",#22846) +typebind(#22846,#22837) +#22847=* +typeexprs(#22847,28,#22833,3,"T exten ... :\n T") +#22848=@"loc,{#10000},75,5,77,5" +locations_default(#22848,#10000,75,5,77,5) +hasLocation(#22847,#22848) +enclosing_stmt(#22847,#22826) +expr_containers(#22847,#22805) #22849=* -scopes(#22849,16) -scopenodes(#22846,#22849) -scopenesting(#22849,#22828) -#22850=@"local_type_name;{U};{#22849}" -local_type_names(#22850,"U",#22849) -#22851=* -typeexprs(#22851,23,#22846,1,"(...arg ... infer U") -#22852=@"loc,{#10000},75,15,75,41" -locations_default(#22852,#10000,75,15,75,41) -hasLocation(#22851,#22852) -enclosing_stmt(#22851,#22825) -expr_containers(#22851,#22805) -#22853=* -exprs(#22853,9,#22851,0,"(...arg ... infer U") -hasLocation(#22853,#22852) -enclosing_stmt(#22853,#22825) -expr_containers(#22853,#22805) +typeexprs(#22849,0,#22847,0,"T") +hasLocation(#22849,#21514) +enclosing_stmt(#22849,#22826) +expr_containers(#22849,#22805) +literals("T","T",#22849) +typebind(#22849,#22830) +#22850=* +scopes(#22850,16) +scopenodes(#22847,#22850) +scopenesting(#22850,#22829) +#22851=@"local_type_name;{U};{#22850}" +local_type_names(#22851,"U",#22850) +#22852=* +typeexprs(#22852,23,#22847,1,"(...arg ... infer U") +#22853=@"loc,{#10000},75,15,75,41" +locations_default(#22853,#10000,75,15,75,41) +hasLocation(#22852,#22853) +enclosing_stmt(#22852,#22826) +expr_containers(#22852,#22805) #22854=* -scopes(#22854,1) -scopenodes(#22853,#22854) -scopenesting(#22854,#22849) -#22855=@"var;{args};{#22854}" -variables(#22855,"args",#22854) -#22856=* -exprs(#22856,78,#22853,0,"args") -hasLocation(#22856,#21522) -expr_containers(#22856,#22853) -literals("args","args",#22856) -decl(#22856,#22855) -#22857=@"var;{arguments};{#22854}" -variables(#22857,"arguments",#22854) -is_arguments_object(#22857) -#22858=* -typeexprs(#22858,29,#22853,-3,"infer U") -#22859=@"loc,{#10000},75,35,75,41" -locations_default(#22859,#10000,75,35,75,41) -hasLocation(#22858,#22859) -expr_containers(#22858,#22853) -#22860=* -typeexprs(#22860,22,#22858,0,"U") -hasLocation(#22860,#21538) -expr_containers(#22860,#22853) +exprs(#22854,9,#22852,0,"(...arg ... infer U") +hasLocation(#22854,#22853) +enclosing_stmt(#22854,#22826) +expr_containers(#22854,#22805) +#22855=* +scopes(#22855,1) +scopenodes(#22854,#22855) +scopenesting(#22855,#22850) +#22856=@"var;{args};{#22855}" +variables(#22856,"args",#22855) +#22857=* +exprs(#22857,78,#22854,0,"args") +hasLocation(#22857,#21522) +expr_containers(#22857,#22854) +literals("args","args",#22857) +decl(#22857,#22856) +#22858=@"var;{arguments};{#22855}" +variables(#22858,"arguments",#22855) +is_arguments_object(#22858) +#22859=* +typeexprs(#22859,29,#22854,-3,"infer U") +#22860=@"loc,{#10000},75,35,75,41" +locations_default(#22860,#10000,75,35,75,41) +hasLocation(#22859,#22860) +expr_containers(#22859,#22854) #22861=* -typeexprs(#22861,1,#22860,0,"U") +typeexprs(#22861,22,#22859,0,"U") hasLocation(#22861,#21538) -expr_containers(#22861,#22853) -literals("U","U",#22861) -typedecl(#22861,#22850) +expr_containers(#22861,#22854) #22862=* -typeexprs(#22862,6,#22853,-6,"any[]") -#22863=@"loc,{#10000},75,25,75,29" -locations_default(#22863,#10000,75,25,75,29) -hasLocation(#22862,#22863) -expr_containers(#22862,#22853) -#22864=* -typeexprs(#22864,2,#22862,0,"any") -hasLocation(#22864,#21526) -expr_containers(#22864,#22853) -literals("any","any",#22864) -has_rest_parameter(#22853) +typeexprs(#22862,1,#22861,0,"U") +hasLocation(#22862,#21538) +expr_containers(#22862,#22854) +literals("U","U",#22862) +typedecl(#22862,#22851) +#22863=* +typeexprs(#22863,6,#22854,-6,"any[]") +#22864=@"loc,{#10000},75,25,75,29" +locations_default(#22864,#10000,75,25,75,29) +hasLocation(#22863,#22864) +expr_containers(#22863,#22854) #22865=* -typeexprs(#22865,0,#22846,2,"U") -hasLocation(#22865,#21542) -enclosing_stmt(#22865,#22825) -expr_containers(#22865,#22805) -literals("U","U",#22865) -typebind(#22865,#22850) +typeexprs(#22865,2,#22863,0,"any") +hasLocation(#22865,#21526) +expr_containers(#22865,#22854) +literals("any","any",#22865) +has_rest_parameter(#22854) #22866=* -typeexprs(#22866,28,#22846,3,"T exten ... :\n T") -#22867=@"loc,{#10000},76,5,77,5" -locations_default(#22867,#10000,76,5,77,5) -hasLocation(#22866,#22867) -enclosing_stmt(#22866,#22825) +typeexprs(#22866,0,#22847,2,"U") +hasLocation(#22866,#21542) +enclosing_stmt(#22866,#22826) expr_containers(#22866,#22805) -#22868=* -typeexprs(#22868,0,#22866,0,"T") -hasLocation(#22868,#21546) -enclosing_stmt(#22868,#22825) -expr_containers(#22868,#22805) -literals("T","T",#22868) -typebind(#22868,#22829) +literals("U","U",#22866) +typebind(#22866,#22851) +#22867=* +typeexprs(#22867,28,#22847,3,"T exten ... :\n T") +#22868=@"loc,{#10000},76,5,77,5" +locations_default(#22868,#10000,76,5,77,5) +hasLocation(#22867,#22868) +enclosing_stmt(#22867,#22826) +expr_containers(#22867,#22805) #22869=* -scopes(#22869,16) -scopenodes(#22866,#22869) -scopenesting(#22869,#22828) -#22870=@"local_type_name;{U};{#22869}" -local_type_names(#22870,"U",#22869) -#22871=* -typeexprs(#22871,14,#22866,1,"Promise") -#22872=@"loc,{#10000},76,15,76,30" -locations_default(#22872,#10000,76,15,76,30) -hasLocation(#22871,#22872) -enclosing_stmt(#22871,#22825) -expr_containers(#22871,#22805) -#22873=* -typeexprs(#22873,0,#22871,-1,"Promise") -hasLocation(#22873,#21550) -enclosing_stmt(#22873,#22825) -expr_containers(#22873,#22805) -literals("Promise","Promise",#22873) +typeexprs(#22869,0,#22867,0,"T") +hasLocation(#22869,#21546) +enclosing_stmt(#22869,#22826) +expr_containers(#22869,#22805) +literals("T","T",#22869) +typebind(#22869,#22830) +#22870=* +scopes(#22870,16) +scopenodes(#22867,#22870) +scopenesting(#22870,#22829) +#22871=@"local_type_name;{U};{#22870}" +local_type_names(#22871,"U",#22870) +#22872=* +typeexprs(#22872,14,#22867,1,"Promise") +#22873=@"loc,{#10000},76,15,76,30" +locations_default(#22873,#10000,76,15,76,30) +hasLocation(#22872,#22873) +enclosing_stmt(#22872,#22826) +expr_containers(#22872,#22805) #22874=* -typeexprs(#22874,29,#22871,0,"infer U") -#22875=@"loc,{#10000},76,23,76,29" -locations_default(#22875,#10000,76,23,76,29) -hasLocation(#22874,#22875) -enclosing_stmt(#22874,#22825) +typeexprs(#22874,0,#22872,-1,"Promise") +hasLocation(#22874,#21550) +enclosing_stmt(#22874,#22826) expr_containers(#22874,#22805) -#22876=* -typeexprs(#22876,22,#22874,0,"U") -hasLocation(#22876,#21556) -enclosing_stmt(#22876,#22825) -expr_containers(#22876,#22805) +literals("Promise","Promise",#22874) +#22875=* +typeexprs(#22875,29,#22872,0,"infer U") +#22876=@"loc,{#10000},76,23,76,29" +locations_default(#22876,#10000,76,23,76,29) +hasLocation(#22875,#22876) +enclosing_stmt(#22875,#22826) +expr_containers(#22875,#22805) #22877=* -typeexprs(#22877,1,#22876,0,"U") +typeexprs(#22877,22,#22875,0,"U") hasLocation(#22877,#21556) -enclosing_stmt(#22877,#22825) +enclosing_stmt(#22877,#22826) expr_containers(#22877,#22805) -literals("U","U",#22877) -typedecl(#22877,#22870) #22878=* -typeexprs(#22878,0,#22866,2,"U") -hasLocation(#22878,#21562) -enclosing_stmt(#22878,#22825) +typeexprs(#22878,1,#22877,0,"U") +hasLocation(#22878,#21556) +enclosing_stmt(#22878,#22826) expr_containers(#22878,#22805) literals("U","U",#22878) -typebind(#22878,#22870) +typedecl(#22878,#22871) #22879=* -typeexprs(#22879,0,#22866,3,"T") -hasLocation(#22879,#21566) -enclosing_stmt(#22879,#22825) +typeexprs(#22879,0,#22867,2,"U") +hasLocation(#22879,#21562) +enclosing_stmt(#22879,#22826) expr_containers(#22879,#22805) -literals("T","T",#22879) -typebind(#22879,#22829) +literals("U","U",#22879) +typebind(#22879,#22871) #22880=* -stmts(#22880,35,#22805,1,"type T0 ... tring>;") -#22881=@"loc,{#10000},79,3,79,29" -locations_default(#22881,#10000,79,3,79,29) -hasLocation(#22880,#22881) -stmt_containers(#22880,#22805) -#22882=* -typeexprs(#22882,1,#22880,0,"T0") -hasLocation(#22882,#21572) -enclosing_stmt(#22882,#22880) -expr_containers(#22882,#22805) -literals("T0","T0",#22882) -typedecl(#22882,#22810) +typeexprs(#22880,0,#22867,3,"T") +hasLocation(#22880,#21566) +enclosing_stmt(#22880,#22826) +expr_containers(#22880,#22805) +literals("T","T",#22880) +typebind(#22880,#22830) +#22881=* +stmts(#22881,35,#22805,1,"type T0 ... tring>;") +#22882=@"loc,{#10000},79,3,79,29" +locations_default(#22882,#10000,79,3,79,29) +hasLocation(#22881,#22882) +stmt_containers(#22881,#22805) #22883=* -typeexprs(#22883,14,#22880,1,"Unpacked") -#22884=@"loc,{#10000},79,13,79,28" -locations_default(#22884,#10000,79,13,79,28) -hasLocation(#22883,#22884) -enclosing_stmt(#22883,#22880) +typeexprs(#22883,1,#22881,0,"T0") +hasLocation(#22883,#21572) +enclosing_stmt(#22883,#22881) expr_containers(#22883,#22805) -#22885=* -typeexprs(#22885,0,#22883,-1,"Unpacked") -hasLocation(#22885,#21576) -enclosing_stmt(#22885,#22880) -expr_containers(#22885,#22805) -literals("Unpacked","Unpacked",#22885) -typebind(#22885,#22809) +literals("T0","T0",#22883) +typedecl(#22883,#22811) +#22884=* +typeexprs(#22884,14,#22881,1,"Unpacked") +#22885=@"loc,{#10000},79,13,79,28" +locations_default(#22885,#10000,79,13,79,28) +hasLocation(#22884,#22885) +enclosing_stmt(#22884,#22881) +expr_containers(#22884,#22805) #22886=* -typeexprs(#22886,2,#22883,0,"string") -hasLocation(#22886,#21580) -enclosing_stmt(#22886,#22880) +typeexprs(#22886,0,#22884,-1,"Unpacked") +hasLocation(#22886,#21576) +enclosing_stmt(#22886,#22881) expr_containers(#22886,#22805) -literals("string","string",#22886) +literals("Unpacked","Unpacked",#22886) +typebind(#22886,#22810) #22887=* -stmts(#22887,35,#22805,2,"type T1 ... ing[]>;") -#22888=@"loc,{#10000},80,3,80,31" -locations_default(#22888,#10000,80,3,80,31) -hasLocation(#22887,#22888) -stmt_containers(#22887,#22805) -#22889=* -typeexprs(#22889,1,#22887,0,"T1") -hasLocation(#22889,#21588) -enclosing_stmt(#22889,#22887) -expr_containers(#22889,#22805) -literals("T1","T1",#22889) -typedecl(#22889,#22811) +typeexprs(#22887,2,#22884,0,"string") +hasLocation(#22887,#21580) +enclosing_stmt(#22887,#22881) +expr_containers(#22887,#22805) +literals("string","string",#22887) +#22888=* +stmts(#22888,35,#22805,2,"type T1 ... ing[]>;") +#22889=@"loc,{#10000},80,3,80,31" +locations_default(#22889,#10000,80,3,80,31) +hasLocation(#22888,#22889) +stmt_containers(#22888,#22805) #22890=* -typeexprs(#22890,14,#22887,1,"Unpacked") -#22891=@"loc,{#10000},80,13,80,30" -locations_default(#22891,#10000,80,13,80,30) -hasLocation(#22890,#22891) -enclosing_stmt(#22890,#22887) +typeexprs(#22890,1,#22888,0,"T1") +hasLocation(#22890,#21588) +enclosing_stmt(#22890,#22888) expr_containers(#22890,#22805) -#22892=* -typeexprs(#22892,0,#22890,-1,"Unpacked") -hasLocation(#22892,#21592) -enclosing_stmt(#22892,#22887) -expr_containers(#22892,#22805) -literals("Unpacked","Unpacked",#22892) -typebind(#22892,#22809) +literals("T1","T1",#22890) +typedecl(#22890,#22812) +#22891=* +typeexprs(#22891,14,#22888,1,"Unpacked") +#22892=@"loc,{#10000},80,13,80,30" +locations_default(#22892,#10000,80,13,80,30) +hasLocation(#22891,#22892) +enclosing_stmt(#22891,#22888) +expr_containers(#22891,#22805) #22893=* -typeexprs(#22893,6,#22890,0,"string[]") -#22894=@"loc,{#10000},80,22,80,29" -locations_default(#22894,#10000,80,22,80,29) -hasLocation(#22893,#22894) -enclosing_stmt(#22893,#22887) +typeexprs(#22893,0,#22891,-1,"Unpacked") +hasLocation(#22893,#21592) +enclosing_stmt(#22893,#22888) expr_containers(#22893,#22805) -#22895=* -typeexprs(#22895,2,#22893,0,"string") -hasLocation(#22895,#21596) -enclosing_stmt(#22895,#22887) -expr_containers(#22895,#22805) -literals("string","string",#22895) +literals("Unpacked","Unpacked",#22893) +typebind(#22893,#22810) +#22894=* +typeexprs(#22894,6,#22891,0,"string[]") +#22895=@"loc,{#10000},80,22,80,29" +locations_default(#22895,#10000,80,22,80,29) +hasLocation(#22894,#22895) +enclosing_stmt(#22894,#22888) +expr_containers(#22894,#22805) #22896=* -stmts(#22896,35,#22805,3,"type T2 ... tring>;") -#22897=@"loc,{#10000},81,3,81,35" -locations_default(#22897,#10000,81,3,81,35) -hasLocation(#22896,#22897) -stmt_containers(#22896,#22805) -#22898=* -typeexprs(#22898,1,#22896,0,"T2") -hasLocation(#22898,#21608) -enclosing_stmt(#22898,#22896) -expr_containers(#22898,#22805) -literals("T2","T2",#22898) -typedecl(#22898,#22812) +typeexprs(#22896,2,#22894,0,"string") +hasLocation(#22896,#21596) +enclosing_stmt(#22896,#22888) +expr_containers(#22896,#22805) +literals("string","string",#22896) +#22897=* +stmts(#22897,35,#22805,3,"type T2 ... tring>;") +#22898=@"loc,{#10000},81,3,81,35" +locations_default(#22898,#10000,81,3,81,35) +hasLocation(#22897,#22898) +stmt_containers(#22897,#22805) #22899=* -typeexprs(#22899,14,#22896,1,"Unpacke ... string>") -#22900=@"loc,{#10000},81,13,81,34" -locations_default(#22900,#10000,81,13,81,34) -hasLocation(#22899,#22900) -enclosing_stmt(#22899,#22896) +typeexprs(#22899,1,#22897,0,"T2") +hasLocation(#22899,#21608) +enclosing_stmt(#22899,#22897) expr_containers(#22899,#22805) -#22901=* -typeexprs(#22901,0,#22899,-1,"Unpacked") -hasLocation(#22901,#21612) -enclosing_stmt(#22901,#22896) -expr_containers(#22901,#22805) -literals("Unpacked","Unpacked",#22901) -typebind(#22901,#22809) +literals("T2","T2",#22899) +typedecl(#22899,#22813) +#22900=* +typeexprs(#22900,14,#22897,1,"Unpacke ... string>") +#22901=@"loc,{#10000},81,13,81,34" +locations_default(#22901,#10000,81,13,81,34) +hasLocation(#22900,#22901) +enclosing_stmt(#22900,#22897) +expr_containers(#22900,#22805) #22902=* -typeexprs(#22902,23,#22899,0,"() => string") -#22903=@"loc,{#10000},81,22,81,33" -locations_default(#22903,#10000,81,22,81,33) -hasLocation(#22902,#22903) -enclosing_stmt(#22902,#22896) +typeexprs(#22902,0,#22900,-1,"Unpacked") +hasLocation(#22902,#21612) +enclosing_stmt(#22902,#22897) expr_containers(#22902,#22805) -#22904=* -exprs(#22904,9,#22902,0,"() => string") -hasLocation(#22904,#22903) -enclosing_stmt(#22904,#22896) -expr_containers(#22904,#22805) +literals("Unpacked","Unpacked",#22902) +typebind(#22902,#22810) +#22903=* +typeexprs(#22903,23,#22900,0,"() => string") +#22904=@"loc,{#10000},81,22,81,33" +locations_default(#22904,#10000,81,22,81,33) +hasLocation(#22903,#22904) +enclosing_stmt(#22903,#22897) +expr_containers(#22903,#22805) #22905=* -scopes(#22905,1) -scopenodes(#22904,#22905) -scopenesting(#22905,#22808) -#22906=@"var;{arguments};{#22905}" -variables(#22906,"arguments",#22905) -is_arguments_object(#22906) -#22907=* -typeexprs(#22907,2,#22904,-3,"string") -hasLocation(#22907,#21622) -expr_containers(#22907,#22904) -literals("string","string",#22907) +exprs(#22905,9,#22903,0,"() => string") +hasLocation(#22905,#22904) +enclosing_stmt(#22905,#22897) +expr_containers(#22905,#22805) +#22906=* +scopes(#22906,1) +scopenodes(#22905,#22906) +scopenesting(#22906,#22808) +#22907=@"var;{arguments};{#22906}" +variables(#22907,"arguments",#22906) +is_arguments_object(#22907) #22908=* -stmts(#22908,35,#22805,4,"type T3 ... ring>>;") -#22909=@"loc,{#10000},82,3,82,38" -locations_default(#22909,#10000,82,3,82,38) -hasLocation(#22908,#22909) -stmt_containers(#22908,#22805) -#22910=* -typeexprs(#22910,1,#22908,0,"T3") -hasLocation(#22910,#21630) -enclosing_stmt(#22910,#22908) -expr_containers(#22910,#22805) -literals("T3","T3",#22910) -typedecl(#22910,#22813) +typeexprs(#22908,2,#22905,-3,"string") +hasLocation(#22908,#21622) +expr_containers(#22908,#22905) +literals("string","string",#22908) +#22909=* +stmts(#22909,35,#22805,4,"type T3 ... ring>>;") +#22910=@"loc,{#10000},82,3,82,38" +locations_default(#22910,#10000,82,3,82,38) +hasLocation(#22909,#22910) +stmt_containers(#22909,#22805) #22911=* -typeexprs(#22911,14,#22908,1,"Unpacke ... tring>>") -#22912=@"loc,{#10000},82,13,82,37" -locations_default(#22912,#10000,82,13,82,37) -hasLocation(#22911,#22912) -enclosing_stmt(#22911,#22908) +typeexprs(#22911,1,#22909,0,"T3") +hasLocation(#22911,#21630) +enclosing_stmt(#22911,#22909) expr_containers(#22911,#22805) -#22913=* -typeexprs(#22913,0,#22911,-1,"Unpacked") -hasLocation(#22913,#21634) -enclosing_stmt(#22913,#22908) -expr_containers(#22913,#22805) -literals("Unpacked","Unpacked",#22913) -typebind(#22913,#22809) +literals("T3","T3",#22911) +typedecl(#22911,#22814) +#22912=* +typeexprs(#22912,14,#22909,1,"Unpacke ... tring>>") +#22913=@"loc,{#10000},82,13,82,37" +locations_default(#22913,#10000,82,13,82,37) +hasLocation(#22912,#22913) +enclosing_stmt(#22912,#22909) +expr_containers(#22912,#22805) #22914=* -typeexprs(#22914,14,#22911,0,"Promise") -#22915=@"loc,{#10000},82,22,82,36" -locations_default(#22915,#10000,82,22,82,36) -hasLocation(#22914,#22915) -enclosing_stmt(#22914,#22908) +typeexprs(#22914,0,#22912,-1,"Unpacked") +hasLocation(#22914,#21634) +enclosing_stmt(#22914,#22909) expr_containers(#22914,#22805) -#22916=* -typeexprs(#22916,0,#22914,-1,"Promise") -hasLocation(#22916,#21638) -enclosing_stmt(#22916,#22908) -expr_containers(#22916,#22805) -literals("Promise","Promise",#22916) +literals("Unpacked","Unpacked",#22914) +typebind(#22914,#22810) +#22915=* +typeexprs(#22915,14,#22912,0,"Promise") +#22916=@"loc,{#10000},82,22,82,36" +locations_default(#22916,#10000,82,22,82,36) +hasLocation(#22915,#22916) +enclosing_stmt(#22915,#22909) +expr_containers(#22915,#22805) #22917=* -typeexprs(#22917,2,#22914,0,"string") -hasLocation(#22917,#21642) -enclosing_stmt(#22917,#22908) +typeexprs(#22917,0,#22915,-1,"Promise") +hasLocation(#22917,#21638) +enclosing_stmt(#22917,#22909) expr_containers(#22917,#22805) -literals("string","string",#22917) +literals("Promise","Promise",#22917) #22918=* -stmts(#22918,35,#22805,5,"type T4 ... ng>[]>;") -#22919=@"loc,{#10000},83,3,83,40" -locations_default(#22919,#10000,83,3,83,40) -hasLocation(#22918,#22919) -stmt_containers(#22918,#22805) -#22920=* -typeexprs(#22920,1,#22918,0,"T4") -hasLocation(#22920,#21652) -enclosing_stmt(#22920,#22918) -expr_containers(#22920,#22805) -literals("T4","T4",#22920) -typedecl(#22920,#22814) +typeexprs(#22918,2,#22915,0,"string") +hasLocation(#22918,#21642) +enclosing_stmt(#22918,#22909) +expr_containers(#22918,#22805) +literals("string","string",#22918) +#22919=* +stmts(#22919,35,#22805,5,"type T4 ... ng>[]>;") +#22920=@"loc,{#10000},83,3,83,40" +locations_default(#22920,#10000,83,3,83,40) +hasLocation(#22919,#22920) +stmt_containers(#22919,#22805) #22921=* -typeexprs(#22921,14,#22918,1,"Unpacke ... ing>[]>") -#22922=@"loc,{#10000},83,13,83,39" -locations_default(#22922,#10000,83,13,83,39) -hasLocation(#22921,#22922) -enclosing_stmt(#22921,#22918) +typeexprs(#22921,1,#22919,0,"T4") +hasLocation(#22921,#21652) +enclosing_stmt(#22921,#22919) expr_containers(#22921,#22805) -#22923=* -typeexprs(#22923,0,#22921,-1,"Unpacked") -hasLocation(#22923,#21656) -enclosing_stmt(#22923,#22918) -expr_containers(#22923,#22805) -literals("Unpacked","Unpacked",#22923) -typebind(#22923,#22809) +literals("T4","T4",#22921) +typedecl(#22921,#22815) +#22922=* +typeexprs(#22922,14,#22919,1,"Unpacke ... ing>[]>") +#22923=@"loc,{#10000},83,13,83,39" +locations_default(#22923,#10000,83,13,83,39) +hasLocation(#22922,#22923) +enclosing_stmt(#22922,#22919) +expr_containers(#22922,#22805) #22924=* -typeexprs(#22924,6,#22921,0,"Promise[]") -#22925=@"loc,{#10000},83,22,83,38" -locations_default(#22925,#10000,83,22,83,38) -hasLocation(#22924,#22925) -enclosing_stmt(#22924,#22918) +typeexprs(#22924,0,#22922,-1,"Unpacked") +hasLocation(#22924,#21656) +enclosing_stmt(#22924,#22919) expr_containers(#22924,#22805) -#22926=* -typeexprs(#22926,14,#22924,0,"Promise") -#22927=@"loc,{#10000},83,22,83,36" -locations_default(#22927,#10000,83,22,83,36) -hasLocation(#22926,#22927) -enclosing_stmt(#22926,#22918) -expr_containers(#22926,#22805) -#22928=* -typeexprs(#22928,0,#22926,-1,"Promise") -hasLocation(#22928,#21660) -enclosing_stmt(#22928,#22918) -expr_containers(#22928,#22805) -literals("Promise","Promise",#22928) +literals("Unpacked","Unpacked",#22924) +typebind(#22924,#22810) +#22925=* +typeexprs(#22925,6,#22922,0,"Promise[]") +#22926=@"loc,{#10000},83,22,83,38" +locations_default(#22926,#10000,83,22,83,38) +hasLocation(#22925,#22926) +enclosing_stmt(#22925,#22919) +expr_containers(#22925,#22805) +#22927=* +typeexprs(#22927,14,#22925,0,"Promise") +#22928=@"loc,{#10000},83,22,83,36" +locations_default(#22928,#10000,83,22,83,36) +hasLocation(#22927,#22928) +enclosing_stmt(#22927,#22919) +expr_containers(#22927,#22805) #22929=* -typeexprs(#22929,2,#22926,0,"string") -hasLocation(#22929,#21664) -enclosing_stmt(#22929,#22918) +typeexprs(#22929,0,#22927,-1,"Promise") +hasLocation(#22929,#21660) +enclosing_stmt(#22929,#22919) expr_containers(#22929,#22805) -literals("string","string",#22929) +literals("Promise","Promise",#22929) #22930=* -stmts(#22930,35,#22805,6,"type T5 ... g>[]>>;") -#22931=@"loc,{#10000},84,3,84,50" -locations_default(#22931,#10000,84,3,84,50) -hasLocation(#22930,#22931) -stmt_containers(#22930,#22805) -#22932=* -typeexprs(#22932,1,#22930,0,"T5") -hasLocation(#22932,#21678) -enclosing_stmt(#22932,#22930) -expr_containers(#22932,#22805) -literals("T5","T5",#22932) -typedecl(#22932,#22815) +typeexprs(#22930,2,#22927,0,"string") +hasLocation(#22930,#21664) +enclosing_stmt(#22930,#22919) +expr_containers(#22930,#22805) +literals("string","string",#22930) +#22931=* +stmts(#22931,35,#22805,6,"type T5 ... g>[]>>;") +#22932=@"loc,{#10000},84,3,84,50" +locations_default(#22932,#10000,84,3,84,50) +hasLocation(#22931,#22932) +stmt_containers(#22931,#22805) #22933=* -typeexprs(#22933,14,#22930,1,"Unpacke ... ng>[]>>") -#22934=@"loc,{#10000},84,13,84,49" -locations_default(#22934,#10000,84,13,84,49) -hasLocation(#22933,#22934) -enclosing_stmt(#22933,#22930) +typeexprs(#22933,1,#22931,0,"T5") +hasLocation(#22933,#21678) +enclosing_stmt(#22933,#22931) expr_containers(#22933,#22805) -#22935=* -typeexprs(#22935,0,#22933,-1,"Unpacked") -hasLocation(#22935,#21682) -enclosing_stmt(#22935,#22930) -expr_containers(#22935,#22805) -literals("Unpacked","Unpacked",#22935) -typebind(#22935,#22809) +literals("T5","T5",#22933) +typedecl(#22933,#22816) +#22934=* +typeexprs(#22934,14,#22931,1,"Unpacke ... ng>[]>>") +#22935=@"loc,{#10000},84,13,84,49" +locations_default(#22935,#10000,84,13,84,49) +hasLocation(#22934,#22935) +enclosing_stmt(#22934,#22931) +expr_containers(#22934,#22805) #22936=* -typeexprs(#22936,14,#22933,0,"Unpacke ... ing>[]>") -#22937=@"loc,{#10000},84,22,84,48" -locations_default(#22937,#10000,84,22,84,48) -hasLocation(#22936,#22937) -enclosing_stmt(#22936,#22930) +typeexprs(#22936,0,#22934,-1,"Unpacked") +hasLocation(#22936,#21682) +enclosing_stmt(#22936,#22931) expr_containers(#22936,#22805) -#22938=* -typeexprs(#22938,0,#22936,-1,"Unpacked") -hasLocation(#22938,#21686) -enclosing_stmt(#22938,#22930) -expr_containers(#22938,#22805) -literals("Unpacked","Unpacked",#22938) -typebind(#22938,#22809) +literals("Unpacked","Unpacked",#22936) +typebind(#22936,#22810) +#22937=* +typeexprs(#22937,14,#22934,0,"Unpacke ... ing>[]>") +#22938=@"loc,{#10000},84,22,84,48" +locations_default(#22938,#10000,84,22,84,48) +hasLocation(#22937,#22938) +enclosing_stmt(#22937,#22931) +expr_containers(#22937,#22805) #22939=* -typeexprs(#22939,6,#22936,0,"Promise[]") -#22940=@"loc,{#10000},84,31,84,47" -locations_default(#22940,#10000,84,31,84,47) -hasLocation(#22939,#22940) -enclosing_stmt(#22939,#22930) +typeexprs(#22939,0,#22937,-1,"Unpacked") +hasLocation(#22939,#21686) +enclosing_stmt(#22939,#22931) expr_containers(#22939,#22805) -#22941=* -typeexprs(#22941,14,#22939,0,"Promise") -#22942=@"loc,{#10000},84,31,84,45" -locations_default(#22942,#10000,84,31,84,45) -hasLocation(#22941,#22942) -enclosing_stmt(#22941,#22930) -expr_containers(#22941,#22805) -#22943=* -typeexprs(#22943,0,#22941,-1,"Promise") -hasLocation(#22943,#21690) -enclosing_stmt(#22943,#22930) -expr_containers(#22943,#22805) -literals("Promise","Promise",#22943) +literals("Unpacked","Unpacked",#22939) +typebind(#22939,#22810) +#22940=* +typeexprs(#22940,6,#22937,0,"Promise[]") +#22941=@"loc,{#10000},84,31,84,47" +locations_default(#22941,#10000,84,31,84,47) +hasLocation(#22940,#22941) +enclosing_stmt(#22940,#22931) +expr_containers(#22940,#22805) +#22942=* +typeexprs(#22942,14,#22940,0,"Promise") +#22943=@"loc,{#10000},84,31,84,45" +locations_default(#22943,#10000,84,31,84,45) +hasLocation(#22942,#22943) +enclosing_stmt(#22942,#22931) +expr_containers(#22942,#22805) #22944=* -typeexprs(#22944,2,#22941,0,"string") -hasLocation(#22944,#21694) -enclosing_stmt(#22944,#22930) +typeexprs(#22944,0,#22942,-1,"Promise") +hasLocation(#22944,#21690) +enclosing_stmt(#22944,#22931) expr_containers(#22944,#22805) -literals("string","string",#22944) +literals("Promise","Promise",#22944) #22945=* -stmts(#22945,35,#22805,7,"type Fo ... never;") -#22946=@"loc,{#10000},86,3,86,65" -locations_default(#22946,#10000,86,3,86,65) -hasLocation(#22945,#22946) -stmt_containers(#22945,#22805) -#22947=* -typeexprs(#22947,1,#22945,0,"Foo") -hasLocation(#22947,#21710) -enclosing_stmt(#22947,#22945) -expr_containers(#22947,#22805) -literals("Foo","Foo",#22947) -typedecl(#22947,#22816) +typeexprs(#22945,2,#22942,0,"string") +hasLocation(#22945,#21694) +enclosing_stmt(#22945,#22931) +expr_containers(#22945,#22805) +literals("string","string",#22945) +#22946=* +stmts(#22946,35,#22805,7,"type Fo ... never;") +#22947=@"loc,{#10000},86,3,86,65" +locations_default(#22947,#10000,86,3,86,65) +hasLocation(#22946,#22947) +stmt_containers(#22946,#22805) #22948=* -scopes(#22948,12) -scopenodes(#22945,#22948) -scopenesting(#22948,#22808) -#22949=@"local_type_name;{T};{#22948}" -local_type_names(#22949,"T",#22948) -#22950=* -typeexprs(#22950,22,#22945,2,"T") -hasLocation(#22950,#21714) -enclosing_stmt(#22950,#22945) -expr_containers(#22950,#22805) +typeexprs(#22948,1,#22946,0,"Foo") +hasLocation(#22948,#21710) +enclosing_stmt(#22948,#22946) +expr_containers(#22948,#22805) +literals("Foo","Foo",#22948) +typedecl(#22948,#22817) +#22949=* +scopes(#22949,12) +scopenodes(#22946,#22949) +scopenesting(#22949,#22808) +#22950=@"local_type_name;{T};{#22949}" +local_type_names(#22950,"T",#22949) #22951=* -typeexprs(#22951,1,#22950,0,"T") +typeexprs(#22951,22,#22946,2,"T") hasLocation(#22951,#21714) -enclosing_stmt(#22951,#22945) +enclosing_stmt(#22951,#22946) expr_containers(#22951,#22805) -literals("T","T",#22951) -typedecl(#22951,#22949) #22952=* -typeexprs(#22952,28,#22945,1,"T exten ... : never") -#22953=@"loc,{#10000},86,17,86,64" -locations_default(#22953,#10000,86,17,86,64) -hasLocation(#22952,#22953) -enclosing_stmt(#22952,#22945) +typeexprs(#22952,1,#22951,0,"T") +hasLocation(#22952,#21714) +enclosing_stmt(#22952,#22946) expr_containers(#22952,#22805) -#22954=* -typeexprs(#22954,0,#22952,0,"T") -hasLocation(#22954,#21720) -enclosing_stmt(#22954,#22945) -expr_containers(#22954,#22805) -literals("T","T",#22954) -typebind(#22954,#22949) +literals("T","T",#22952) +typedecl(#22952,#22950) +#22953=* +typeexprs(#22953,28,#22946,1,"T exten ... : never") +#22954=@"loc,{#10000},86,17,86,64" +locations_default(#22954,#10000,86,17,86,64) +hasLocation(#22953,#22954) +enclosing_stmt(#22953,#22946) +expr_containers(#22953,#22805) #22955=* -typeexprs(#22955,21,#22952,1,"{ a: in ... fer U }") -#22956=@"loc,{#10000},86,27,86,52" -locations_default(#22956,#10000,86,27,86,52) -hasLocation(#22955,#22956) -enclosing_stmt(#22955,#22945) +typeexprs(#22955,0,#22953,0,"T") +hasLocation(#22955,#21720) +enclosing_stmt(#22955,#22946) expr_containers(#22955,#22805) -#22957=* -properties(#22957,#22955,0,8,"a: infer U,") -#22958=@"loc,{#10000},86,29,86,39" -locations_default(#22958,#10000,86,29,86,39) -hasLocation(#22957,#22958) -#22959=* -exprs(#22959,0,#22957,0,"a") -hasLocation(#22959,#21726) -enclosing_stmt(#22959,#22945) -expr_containers(#22959,#22805) -literals("a","a",#22959) -is_abstract_member(#22957) +literals("T","T",#22955) +typebind(#22955,#22950) +#22956=* +typeexprs(#22956,21,#22953,1,"{ a: in ... fer U }") +#22957=@"loc,{#10000},86,27,86,52" +locations_default(#22957,#10000,86,27,86,52) +hasLocation(#22956,#22957) +enclosing_stmt(#22956,#22946) +expr_containers(#22956,#22805) +#22958=* +properties(#22958,#22956,0,8,"a: infer U,") +#22959=@"loc,{#10000},86,29,86,39" +locations_default(#22959,#10000,86,29,86,39) +hasLocation(#22958,#22959) #22960=* -typeexprs(#22960,29,#22957,2,"infer U") -#22961=@"loc,{#10000},86,32,86,38" -locations_default(#22961,#10000,86,32,86,38) -hasLocation(#22960,#22961) -enclosing_stmt(#22960,#22945) +exprs(#22960,0,#22958,0,"a") +hasLocation(#22960,#21726) +enclosing_stmt(#22960,#22946) expr_containers(#22960,#22805) -#22962=* -typeexprs(#22962,22,#22960,0,"U") -hasLocation(#22962,#21732) -enclosing_stmt(#22962,#22945) -expr_containers(#22962,#22805) +literals("a","a",#22960) +is_abstract_member(#22958) +#22961=* +typeexprs(#22961,29,#22958,2,"infer U") +#22962=@"loc,{#10000},86,32,86,38" +locations_default(#22962,#10000,86,32,86,38) +hasLocation(#22961,#22962) +enclosing_stmt(#22961,#22946) +expr_containers(#22961,#22805) #22963=* -typeexprs(#22963,1,#22962,0,"U") +typeexprs(#22963,22,#22961,0,"U") hasLocation(#22963,#21732) -enclosing_stmt(#22963,#22945) +enclosing_stmt(#22963,#22946) expr_containers(#22963,#22805) -literals("U","U",#22963) #22964=* -properties(#22964,#22955,1,8,"b: infer U") -#22965=@"loc,{#10000},86,41,86,50" -locations_default(#22965,#10000,86,41,86,50) -hasLocation(#22964,#22965) -#22966=* -exprs(#22966,0,#22964,0,"b") -hasLocation(#22966,#21736) -enclosing_stmt(#22966,#22945) -expr_containers(#22966,#22805) -literals("b","b",#22966) -is_abstract_member(#22964) +typeexprs(#22964,1,#22963,0,"U") +hasLocation(#22964,#21732) +enclosing_stmt(#22964,#22946) +expr_containers(#22964,#22805) +literals("U","U",#22964) +#22965=* +properties(#22965,#22956,1,8,"b: infer U") +#22966=@"loc,{#10000},86,41,86,50" +locations_default(#22966,#10000,86,41,86,50) +hasLocation(#22965,#22966) #22967=* -typeexprs(#22967,29,#22964,2,"infer U") -#22968=@"loc,{#10000},86,44,86,50" -locations_default(#22968,#10000,86,44,86,50) -hasLocation(#22967,#22968) -enclosing_stmt(#22967,#22945) +exprs(#22967,0,#22965,0,"b") +hasLocation(#22967,#21736) +enclosing_stmt(#22967,#22946) expr_containers(#22967,#22805) -#22969=* -typeexprs(#22969,22,#22967,0,"U") -hasLocation(#22969,#21742) -enclosing_stmt(#22969,#22945) -expr_containers(#22969,#22805) +literals("b","b",#22967) +is_abstract_member(#22965) +#22968=* +typeexprs(#22968,29,#22965,2,"infer U") +#22969=@"loc,{#10000},86,44,86,50" +locations_default(#22969,#10000,86,44,86,50) +hasLocation(#22968,#22969) +enclosing_stmt(#22968,#22946) +expr_containers(#22968,#22805) #22970=* -typeexprs(#22970,1,#22969,0,"U") +typeexprs(#22970,22,#22968,0,"U") hasLocation(#22970,#21742) -enclosing_stmt(#22970,#22945) +enclosing_stmt(#22970,#22946) expr_containers(#22970,#22805) -literals("U","U",#22970) #22971=* -typeexprs(#22971,0,#22952,2,"U") -hasLocation(#22971,#21748) -enclosing_stmt(#22971,#22945) +typeexprs(#22971,1,#22970,0,"U") +hasLocation(#22971,#21742) +enclosing_stmt(#22971,#22946) expr_containers(#22971,#22805) literals("U","U",#22971) #22972=* -typeexprs(#22972,2,#22952,3,"never") -hasLocation(#22972,#21752) -enclosing_stmt(#22972,#22945) +typeexprs(#22972,0,#22953,2,"U") +hasLocation(#22972,#21748) +enclosing_stmt(#22972,#22946) expr_containers(#22972,#22805) -literals("never","never",#22972) +literals("U","U",#22972) #22973=* -stmts(#22973,35,#22805,8,"type T1 ... ing }>;") -#22974=@"loc,{#10000},87,3,87,43" -locations_default(#22974,#10000,87,3,87,43) -hasLocation(#22973,#22974) -stmt_containers(#22973,#22805) -#22975=* -typeexprs(#22975,1,#22973,0,"T10") -hasLocation(#22975,#21758) -enclosing_stmt(#22975,#22973) -expr_containers(#22975,#22805) -literals("T10","T10",#22975) -typedecl(#22975,#22817) +typeexprs(#22973,2,#22953,3,"never") +hasLocation(#22973,#21752) +enclosing_stmt(#22973,#22946) +expr_containers(#22973,#22805) +literals("never","never",#22973) +#22974=* +stmts(#22974,35,#22805,8,"type T1 ... ing }>;") +#22975=@"loc,{#10000},87,3,87,43" +locations_default(#22975,#10000,87,3,87,43) +hasLocation(#22974,#22975) +stmt_containers(#22974,#22805) #22976=* -typeexprs(#22976,14,#22973,1,"Foo<{ a ... ring }>") -#22977=@"loc,{#10000},87,14,87,42" -locations_default(#22977,#10000,87,14,87,42) -hasLocation(#22976,#22977) -enclosing_stmt(#22976,#22973) +typeexprs(#22976,1,#22974,0,"T10") +hasLocation(#22976,#21758) +enclosing_stmt(#22976,#22974) expr_containers(#22976,#22805) -#22978=* -typeexprs(#22978,0,#22976,-1,"Foo") -hasLocation(#22978,#21762) -enclosing_stmt(#22978,#22973) -expr_containers(#22978,#22805) -literals("Foo","Foo",#22978) -typebind(#22978,#22816) +literals("T10","T10",#22976) +typedecl(#22976,#22818) +#22977=* +typeexprs(#22977,14,#22974,1,"Foo<{ a ... ring }>") +#22978=@"loc,{#10000},87,14,87,42" +locations_default(#22978,#10000,87,14,87,42) +hasLocation(#22977,#22978) +enclosing_stmt(#22977,#22974) +expr_containers(#22977,#22805) #22979=* -typeexprs(#22979,21,#22976,0,"{ a: st ... tring }") -#22980=@"loc,{#10000},87,18,87,41" -locations_default(#22980,#10000,87,18,87,41) -hasLocation(#22979,#22980) -enclosing_stmt(#22979,#22973) +typeexprs(#22979,0,#22977,-1,"Foo") +hasLocation(#22979,#21762) +enclosing_stmt(#22979,#22974) expr_containers(#22979,#22805) -#22981=* -properties(#22981,#22979,0,8,"a: string,") -#22982=@"loc,{#10000},87,20,87,29" -locations_default(#22982,#10000,87,20,87,29) -hasLocation(#22981,#22982) -#22983=* -exprs(#22983,0,#22981,0,"a") -hasLocation(#22983,#21768) -enclosing_stmt(#22983,#22973) -expr_containers(#22983,#22805) -literals("a","a",#22983) -is_abstract_member(#22981) +literals("Foo","Foo",#22979) +typebind(#22979,#22817) +#22980=* +typeexprs(#22980,21,#22977,0,"{ a: st ... tring }") +#22981=@"loc,{#10000},87,18,87,41" +locations_default(#22981,#10000,87,18,87,41) +hasLocation(#22980,#22981) +enclosing_stmt(#22980,#22974) +expr_containers(#22980,#22805) +#22982=* +properties(#22982,#22980,0,8,"a: string,") +#22983=@"loc,{#10000},87,20,87,29" +locations_default(#22983,#10000,87,20,87,29) +hasLocation(#22982,#22983) #22984=* -typeexprs(#22984,2,#22981,2,"string") -hasLocation(#22984,#21772) -enclosing_stmt(#22984,#22973) +exprs(#22984,0,#22982,0,"a") +hasLocation(#22984,#21768) +enclosing_stmt(#22984,#22974) expr_containers(#22984,#22805) -literals("string","string",#22984) +literals("a","a",#22984) +is_abstract_member(#22982) #22985=* -properties(#22985,#22979,1,8,"b: string") -#22986=@"loc,{#10000},87,31,87,39" -locations_default(#22986,#10000,87,31,87,39) -hasLocation(#22985,#22986) -#22987=* -exprs(#22987,0,#22985,0,"b") -hasLocation(#22987,#21776) -enclosing_stmt(#22987,#22973) -expr_containers(#22987,#22805) -literals("b","b",#22987) -is_abstract_member(#22985) +typeexprs(#22985,2,#22982,2,"string") +hasLocation(#22985,#21772) +enclosing_stmt(#22985,#22974) +expr_containers(#22985,#22805) +literals("string","string",#22985) +#22986=* +properties(#22986,#22980,1,8,"b: string") +#22987=@"loc,{#10000},87,31,87,39" +locations_default(#22987,#10000,87,31,87,39) +hasLocation(#22986,#22987) #22988=* -typeexprs(#22988,2,#22985,2,"string") -hasLocation(#22988,#21780) -enclosing_stmt(#22988,#22973) +exprs(#22988,0,#22986,0,"b") +hasLocation(#22988,#21776) +enclosing_stmt(#22988,#22974) expr_containers(#22988,#22805) -literals("string","string",#22988) +literals("b","b",#22988) +is_abstract_member(#22986) #22989=* -stmts(#22989,35,#22805,9,"type T1 ... ber }>;") -#22990=@"loc,{#10000},88,3,88,43" -locations_default(#22990,#10000,88,3,88,43) -hasLocation(#22989,#22990) -stmt_containers(#22989,#22805) -#22991=* -typeexprs(#22991,1,#22989,0,"T11") -hasLocation(#22991,#21790) -enclosing_stmt(#22991,#22989) -expr_containers(#22991,#22805) -literals("T11","T11",#22991) -typedecl(#22991,#22818) +typeexprs(#22989,2,#22986,2,"string") +hasLocation(#22989,#21780) +enclosing_stmt(#22989,#22974) +expr_containers(#22989,#22805) +literals("string","string",#22989) +#22990=* +stmts(#22990,35,#22805,9,"type T1 ... ber }>;") +#22991=@"loc,{#10000},88,3,88,43" +locations_default(#22991,#10000,88,3,88,43) +hasLocation(#22990,#22991) +stmt_containers(#22990,#22805) #22992=* -typeexprs(#22992,14,#22989,1,"Foo<{ a ... mber }>") -#22993=@"loc,{#10000},88,14,88,42" -locations_default(#22993,#10000,88,14,88,42) -hasLocation(#22992,#22993) -enclosing_stmt(#22992,#22989) +typeexprs(#22992,1,#22990,0,"T11") +hasLocation(#22992,#21790) +enclosing_stmt(#22992,#22990) expr_containers(#22992,#22805) -#22994=* -typeexprs(#22994,0,#22992,-1,"Foo") -hasLocation(#22994,#21794) -enclosing_stmt(#22994,#22989) -expr_containers(#22994,#22805) -literals("Foo","Foo",#22994) -typebind(#22994,#22816) +literals("T11","T11",#22992) +typedecl(#22992,#22819) +#22993=* +typeexprs(#22993,14,#22990,1,"Foo<{ a ... mber }>") +#22994=@"loc,{#10000},88,14,88,42" +locations_default(#22994,#10000,88,14,88,42) +hasLocation(#22993,#22994) +enclosing_stmt(#22993,#22990) +expr_containers(#22993,#22805) #22995=* -typeexprs(#22995,21,#22992,0,"{ a: st ... umber }") -#22996=@"loc,{#10000},88,18,88,41" -locations_default(#22996,#10000,88,18,88,41) -hasLocation(#22995,#22996) -enclosing_stmt(#22995,#22989) +typeexprs(#22995,0,#22993,-1,"Foo") +hasLocation(#22995,#21794) +enclosing_stmt(#22995,#22990) expr_containers(#22995,#22805) -#22997=* -properties(#22997,#22995,0,8,"a: string,") -#22998=@"loc,{#10000},88,20,88,29" -locations_default(#22998,#10000,88,20,88,29) -hasLocation(#22997,#22998) -#22999=* -exprs(#22999,0,#22997,0,"a") -hasLocation(#22999,#21800) -enclosing_stmt(#22999,#22989) -expr_containers(#22999,#22805) -literals("a","a",#22999) -is_abstract_member(#22997) +literals("Foo","Foo",#22995) +typebind(#22995,#22817) +#22996=* +typeexprs(#22996,21,#22993,0,"{ a: st ... umber }") +#22997=@"loc,{#10000},88,18,88,41" +locations_default(#22997,#10000,88,18,88,41) +hasLocation(#22996,#22997) +enclosing_stmt(#22996,#22990) +expr_containers(#22996,#22805) +#22998=* +properties(#22998,#22996,0,8,"a: string,") +#22999=@"loc,{#10000},88,20,88,29" +locations_default(#22999,#10000,88,20,88,29) +hasLocation(#22998,#22999) #23000=* -typeexprs(#23000,2,#22997,2,"string") -hasLocation(#23000,#21804) -enclosing_stmt(#23000,#22989) +exprs(#23000,0,#22998,0,"a") +hasLocation(#23000,#21800) +enclosing_stmt(#23000,#22990) expr_containers(#23000,#22805) -literals("string","string",#23000) +literals("a","a",#23000) +is_abstract_member(#22998) #23001=* -properties(#23001,#22995,1,8,"b: number") -#23002=@"loc,{#10000},88,31,88,39" -locations_default(#23002,#10000,88,31,88,39) -hasLocation(#23001,#23002) -#23003=* -exprs(#23003,0,#23001,0,"b") -hasLocation(#23003,#21808) -enclosing_stmt(#23003,#22989) -expr_containers(#23003,#22805) -literals("b","b",#23003) -is_abstract_member(#23001) +typeexprs(#23001,2,#22998,2,"string") +hasLocation(#23001,#21804) +enclosing_stmt(#23001,#22990) +expr_containers(#23001,#22805) +literals("string","string",#23001) +#23002=* +properties(#23002,#22996,1,8,"b: number") +#23003=@"loc,{#10000},88,31,88,39" +locations_default(#23003,#10000,88,31,88,39) +hasLocation(#23002,#23003) #23004=* -typeexprs(#23004,2,#23001,2,"number") -hasLocation(#23004,#21812) -enclosing_stmt(#23004,#22989) +exprs(#23004,0,#23002,0,"b") +hasLocation(#23004,#21808) +enclosing_stmt(#23004,#22990) expr_containers(#23004,#22805) -literals("number","number",#23004) +literals("b","b",#23004) +is_abstract_member(#23002) #23005=* -stmts(#23005,35,#22805,10,"type Ba ... never;") -#23006=@"loc,{#10000},90,3,90,91" -locations_default(#23006,#10000,90,3,90,91) -hasLocation(#23005,#23006) -stmt_containers(#23005,#22805) -#23007=* -typeexprs(#23007,1,#23005,0,"Bar") -hasLocation(#23007,#21822) -enclosing_stmt(#23007,#23005) -expr_containers(#23007,#22805) -literals("Bar","Bar",#23007) -typedecl(#23007,#22819) +typeexprs(#23005,2,#23002,2,"number") +hasLocation(#23005,#21812) +enclosing_stmt(#23005,#22990) +expr_containers(#23005,#22805) +literals("number","number",#23005) +#23006=* +stmts(#23006,35,#22805,10,"type Ba ... never;") +#23007=@"loc,{#10000},90,3,90,91" +locations_default(#23007,#10000,90,3,90,91) +hasLocation(#23006,#23007) +stmt_containers(#23006,#22805) #23008=* -scopes(#23008,12) -scopenodes(#23005,#23008) -scopenesting(#23008,#22808) -#23009=@"local_type_name;{T};{#23008}" -local_type_names(#23009,"T",#23008) -#23010=* -typeexprs(#23010,22,#23005,2,"T") -hasLocation(#23010,#21826) -enclosing_stmt(#23010,#23005) -expr_containers(#23010,#22805) +typeexprs(#23008,1,#23006,0,"Bar") +hasLocation(#23008,#21822) +enclosing_stmt(#23008,#23006) +expr_containers(#23008,#22805) +literals("Bar","Bar",#23008) +typedecl(#23008,#22820) +#23009=* +scopes(#23009,12) +scopenodes(#23006,#23009) +scopenesting(#23009,#22808) +#23010=@"local_type_name;{T};{#23009}" +local_type_names(#23010,"T",#23009) #23011=* -typeexprs(#23011,1,#23010,0,"T") +typeexprs(#23011,22,#23006,2,"T") hasLocation(#23011,#21826) -enclosing_stmt(#23011,#23005) +enclosing_stmt(#23011,#23006) expr_containers(#23011,#22805) -literals("T","T",#23011) -typedecl(#23011,#23009) #23012=* -typeexprs(#23012,28,#23005,1,"T exten ... : never") -#23013=@"loc,{#10000},90,17,90,90" -locations_default(#23013,#10000,90,17,90,90) -hasLocation(#23012,#23013) -enclosing_stmt(#23012,#23005) +typeexprs(#23012,1,#23011,0,"T") +hasLocation(#23012,#21826) +enclosing_stmt(#23012,#23006) expr_containers(#23012,#22805) -#23014=* -typeexprs(#23014,0,#23012,0,"T") -hasLocation(#23014,#21832) -enclosing_stmt(#23014,#23005) -expr_containers(#23014,#22805) -literals("T","T",#23014) -typebind(#23014,#23009) +literals("T","T",#23012) +typedecl(#23012,#23010) +#23013=* +typeexprs(#23013,28,#23006,1,"T exten ... : never") +#23014=@"loc,{#10000},90,17,90,90" +locations_default(#23014,#10000,90,17,90,90) +hasLocation(#23013,#23014) +enclosing_stmt(#23013,#23006) +expr_containers(#23013,#22805) #23015=* -typeexprs(#23015,21,#23012,1,"{ a: (x ... void }") -#23016=@"loc,{#10000},90,27,90,78" -locations_default(#23016,#10000,90,27,90,78) -hasLocation(#23015,#23016) -enclosing_stmt(#23015,#23005) +typeexprs(#23015,0,#23013,0,"T") +hasLocation(#23015,#21832) +enclosing_stmt(#23015,#23006) expr_containers(#23015,#22805) -#23017=* -properties(#23017,#23015,0,8,"a: (x: ... > void,") -#23018=@"loc,{#10000},90,29,90,52" -locations_default(#23018,#10000,90,29,90,52) -hasLocation(#23017,#23018) -#23019=* -exprs(#23019,0,#23017,0,"a") -hasLocation(#23019,#21838) -enclosing_stmt(#23019,#23005) -expr_containers(#23019,#22805) -literals("a","a",#23019) -is_abstract_member(#23017) +literals("T","T",#23015) +typebind(#23015,#23010) +#23016=* +typeexprs(#23016,21,#23013,1,"{ a: (x ... void }") +#23017=@"loc,{#10000},90,27,90,78" +locations_default(#23017,#10000,90,27,90,78) +hasLocation(#23016,#23017) +enclosing_stmt(#23016,#23006) +expr_containers(#23016,#22805) +#23018=* +properties(#23018,#23016,0,8,"a: (x: ... > void,") +#23019=@"loc,{#10000},90,29,90,52" +locations_default(#23019,#10000,90,29,90,52) +hasLocation(#23018,#23019) #23020=* -typeexprs(#23020,23,#23017,2,"(x: infer U) => void") -#23021=@"loc,{#10000},90,32,90,51" -locations_default(#23021,#10000,90,32,90,51) -hasLocation(#23020,#23021) -enclosing_stmt(#23020,#23005) +exprs(#23020,0,#23018,0,"a") +hasLocation(#23020,#21838) +enclosing_stmt(#23020,#23006) expr_containers(#23020,#22805) -#23022=* -exprs(#23022,9,#23020,0,"(x: infer U) => void") -hasLocation(#23022,#23021) -enclosing_stmt(#23022,#23005) -expr_containers(#23022,#22805) +literals("a","a",#23020) +is_abstract_member(#23018) +#23021=* +typeexprs(#23021,23,#23018,2,"(x: infer U) => void") +#23022=@"loc,{#10000},90,32,90,51" +locations_default(#23022,#10000,90,32,90,51) +hasLocation(#23021,#23022) +enclosing_stmt(#23021,#23006) +expr_containers(#23021,#22805) #23023=* -scopes(#23023,1) -scopenodes(#23022,#23023) -scopenesting(#23023,#23008) -#23024=@"var;{x};{#23023}" -variables(#23024,"x",#23023) -#23025=* -exprs(#23025,78,#23022,0,"x") -hasLocation(#23025,#21844) -expr_containers(#23025,#23022) -literals("x","x",#23025) -decl(#23025,#23024) -#23026=@"var;{arguments};{#23023}" -variables(#23026,"arguments",#23023) -is_arguments_object(#23026) -#23027=* -typeexprs(#23027,2,#23022,-3,"void") -hasLocation(#23027,#21856) -expr_containers(#23027,#23022) -literals("void","void",#23027) +exprs(#23023,9,#23021,0,"(x: infer U) => void") +hasLocation(#23023,#23022) +enclosing_stmt(#23023,#23006) +expr_containers(#23023,#22805) +#23024=* +scopes(#23024,1) +scopenodes(#23023,#23024) +scopenesting(#23024,#23009) +#23025=@"var;{x};{#23024}" +variables(#23025,"x",#23024) +#23026=* +exprs(#23026,78,#23023,0,"x") +hasLocation(#23026,#21844) +expr_containers(#23026,#23023) +literals("x","x",#23026) +decl(#23026,#23025) +#23027=@"var;{arguments};{#23024}" +variables(#23027,"arguments",#23024) +is_arguments_object(#23027) #23028=* -typeexprs(#23028,29,#23022,-6,"infer U") -#23029=@"loc,{#10000},90,36,90,42" -locations_default(#23029,#10000,90,36,90,42) -hasLocation(#23028,#23029) -expr_containers(#23028,#23022) -#23030=* -typeexprs(#23030,22,#23028,0,"U") -hasLocation(#23030,#21850) -expr_containers(#23030,#23022) +typeexprs(#23028,2,#23023,-3,"void") +hasLocation(#23028,#21856) +expr_containers(#23028,#23023) +literals("void","void",#23028) +#23029=* +typeexprs(#23029,29,#23023,-6,"infer U") +#23030=@"loc,{#10000},90,36,90,42" +locations_default(#23030,#10000,90,36,90,42) +hasLocation(#23029,#23030) +expr_containers(#23029,#23023) #23031=* -typeexprs(#23031,1,#23030,0,"U") +typeexprs(#23031,22,#23029,0,"U") hasLocation(#23031,#21850) -expr_containers(#23031,#23022) -literals("U","U",#23031) +expr_containers(#23031,#23023) #23032=* -properties(#23032,#23015,1,8,"b: (x: ... => void") -#23033=@"loc,{#10000},90,54,90,76" -locations_default(#23033,#10000,90,54,90,76) -hasLocation(#23032,#23033) -#23034=* -exprs(#23034,0,#23032,0,"b") -hasLocation(#23034,#21860) -enclosing_stmt(#23034,#23005) -expr_containers(#23034,#22805) -literals("b","b",#23034) -is_abstract_member(#23032) +typeexprs(#23032,1,#23031,0,"U") +hasLocation(#23032,#21850) +expr_containers(#23032,#23023) +literals("U","U",#23032) +#23033=* +properties(#23033,#23016,1,8,"b: (x: ... => void") +#23034=@"loc,{#10000},90,54,90,76" +locations_default(#23034,#10000,90,54,90,76) +hasLocation(#23033,#23034) #23035=* -typeexprs(#23035,23,#23032,2,"(x: infer U) => void") -#23036=@"loc,{#10000},90,57,90,76" -locations_default(#23036,#10000,90,57,90,76) -hasLocation(#23035,#23036) -enclosing_stmt(#23035,#23005) +exprs(#23035,0,#23033,0,"b") +hasLocation(#23035,#21860) +enclosing_stmt(#23035,#23006) expr_containers(#23035,#22805) -#23037=* -exprs(#23037,9,#23035,0,"(x: infer U) => void") -hasLocation(#23037,#23036) -enclosing_stmt(#23037,#23005) -expr_containers(#23037,#22805) +literals("b","b",#23035) +is_abstract_member(#23033) +#23036=* +typeexprs(#23036,23,#23033,2,"(x: infer U) => void") +#23037=@"loc,{#10000},90,57,90,76" +locations_default(#23037,#10000,90,57,90,76) +hasLocation(#23036,#23037) +enclosing_stmt(#23036,#23006) +expr_containers(#23036,#22805) #23038=* -scopes(#23038,1) -scopenodes(#23037,#23038) -scopenesting(#23038,#23008) -#23039=@"var;{x};{#23038}" -variables(#23039,"x",#23038) -#23040=* -exprs(#23040,78,#23037,0,"x") -hasLocation(#23040,#21866) -expr_containers(#23040,#23037) -literals("x","x",#23040) -decl(#23040,#23039) -#23041=@"var;{arguments};{#23038}" -variables(#23041,"arguments",#23038) -is_arguments_object(#23041) -#23042=* -typeexprs(#23042,2,#23037,-3,"void") -hasLocation(#23042,#21878) -expr_containers(#23042,#23037) -literals("void","void",#23042) +exprs(#23038,9,#23036,0,"(x: infer U) => void") +hasLocation(#23038,#23037) +enclosing_stmt(#23038,#23006) +expr_containers(#23038,#22805) +#23039=* +scopes(#23039,1) +scopenodes(#23038,#23039) +scopenesting(#23039,#23009) +#23040=@"var;{x};{#23039}" +variables(#23040,"x",#23039) +#23041=* +exprs(#23041,78,#23038,0,"x") +hasLocation(#23041,#21866) +expr_containers(#23041,#23038) +literals("x","x",#23041) +decl(#23041,#23040) +#23042=@"var;{arguments};{#23039}" +variables(#23042,"arguments",#23039) +is_arguments_object(#23042) #23043=* -typeexprs(#23043,29,#23037,-6,"infer U") -#23044=@"loc,{#10000},90,61,90,67" -locations_default(#23044,#10000,90,61,90,67) -hasLocation(#23043,#23044) -expr_containers(#23043,#23037) -#23045=* -typeexprs(#23045,22,#23043,0,"U") -hasLocation(#23045,#21872) -expr_containers(#23045,#23037) +typeexprs(#23043,2,#23038,-3,"void") +hasLocation(#23043,#21878) +expr_containers(#23043,#23038) +literals("void","void",#23043) +#23044=* +typeexprs(#23044,29,#23038,-6,"infer U") +#23045=@"loc,{#10000},90,61,90,67" +locations_default(#23045,#10000,90,61,90,67) +hasLocation(#23044,#23045) +expr_containers(#23044,#23038) #23046=* -typeexprs(#23046,1,#23045,0,"U") +typeexprs(#23046,22,#23044,0,"U") hasLocation(#23046,#21872) -expr_containers(#23046,#23037) -literals("U","U",#23046) +expr_containers(#23046,#23038) #23047=* -typeexprs(#23047,0,#23012,2,"U") -hasLocation(#23047,#21884) -enclosing_stmt(#23047,#23005) -expr_containers(#23047,#22805) +typeexprs(#23047,1,#23046,0,"U") +hasLocation(#23047,#21872) +expr_containers(#23047,#23038) literals("U","U",#23047) #23048=* -typeexprs(#23048,2,#23012,3,"never") -hasLocation(#23048,#21888) -enclosing_stmt(#23048,#23005) +typeexprs(#23048,0,#23013,2,"U") +hasLocation(#23048,#21884) +enclosing_stmt(#23048,#23006) expr_containers(#23048,#22805) -literals("never","never",#23048) +literals("U","U",#23048) #23049=* -stmts(#23049,35,#22805,11,"type T2 ... oid }>;") -#23050=@"loc,{#10000},91,3,91,69" -locations_default(#23050,#10000,91,3,91,69) -hasLocation(#23049,#23050) -stmt_containers(#23049,#22805) -#23051=* -typeexprs(#23051,1,#23049,0,"T20") -hasLocation(#23051,#21894) -enclosing_stmt(#23051,#23049) -expr_containers(#23051,#22805) -literals("T20","T20",#23051) -typedecl(#23051,#22820) +typeexprs(#23049,2,#23013,3,"never") +hasLocation(#23049,#21888) +enclosing_stmt(#23049,#23006) +expr_containers(#23049,#22805) +literals("never","never",#23049) +#23050=* +stmts(#23050,35,#22805,11,"type T2 ... oid }>;") +#23051=@"loc,{#10000},91,3,91,69" +locations_default(#23051,#10000,91,3,91,69) +hasLocation(#23050,#23051) +stmt_containers(#23050,#22805) #23052=* -typeexprs(#23052,14,#23049,1,"Bar<{ a ... void }>") -#23053=@"loc,{#10000},91,14,91,68" -locations_default(#23053,#10000,91,14,91,68) -hasLocation(#23052,#23053) -enclosing_stmt(#23052,#23049) +typeexprs(#23052,1,#23050,0,"T20") +hasLocation(#23052,#21894) +enclosing_stmt(#23052,#23050) expr_containers(#23052,#22805) -#23054=* -typeexprs(#23054,0,#23052,-1,"Bar") -hasLocation(#23054,#21898) -enclosing_stmt(#23054,#23049) -expr_containers(#23054,#22805) -literals("Bar","Bar",#23054) -typebind(#23054,#22819) +literals("T20","T20",#23052) +typedecl(#23052,#22821) +#23053=* +typeexprs(#23053,14,#23050,1,"Bar<{ a ... void }>") +#23054=@"loc,{#10000},91,14,91,68" +locations_default(#23054,#10000,91,14,91,68) +hasLocation(#23053,#23054) +enclosing_stmt(#23053,#23050) +expr_containers(#23053,#22805) #23055=* -typeexprs(#23055,21,#23052,0,"{ a: (x ... void }") -#23056=@"loc,{#10000},91,18,91,67" -locations_default(#23056,#10000,91,18,91,67) -hasLocation(#23055,#23056) -enclosing_stmt(#23055,#23049) +typeexprs(#23055,0,#23053,-1,"Bar") +hasLocation(#23055,#21898) +enclosing_stmt(#23055,#23050) expr_containers(#23055,#22805) -#23057=* -properties(#23057,#23055,0,8,"a: (x: ... > void,") -#23058=@"loc,{#10000},91,20,91,42" -locations_default(#23058,#10000,91,20,91,42) -hasLocation(#23057,#23058) -#23059=* -exprs(#23059,0,#23057,0,"a") -hasLocation(#23059,#21904) -enclosing_stmt(#23059,#23049) -expr_containers(#23059,#22805) -literals("a","a",#23059) -is_abstract_member(#23057) +literals("Bar","Bar",#23055) +typebind(#23055,#22820) +#23056=* +typeexprs(#23056,21,#23053,0,"{ a: (x ... void }") +#23057=@"loc,{#10000},91,18,91,67" +locations_default(#23057,#10000,91,18,91,67) +hasLocation(#23056,#23057) +enclosing_stmt(#23056,#23050) +expr_containers(#23056,#22805) +#23058=* +properties(#23058,#23056,0,8,"a: (x: ... > void,") +#23059=@"loc,{#10000},91,20,91,42" +locations_default(#23059,#10000,91,20,91,42) +hasLocation(#23058,#23059) #23060=* -typeexprs(#23060,23,#23057,2,"(x: string) => void") -#23061=@"loc,{#10000},91,23,91,41" -locations_default(#23061,#10000,91,23,91,41) -hasLocation(#23060,#23061) -enclosing_stmt(#23060,#23049) +exprs(#23060,0,#23058,0,"a") +hasLocation(#23060,#21904) +enclosing_stmt(#23060,#23050) expr_containers(#23060,#22805) -#23062=* -exprs(#23062,9,#23060,0,"(x: string) => void") -hasLocation(#23062,#23061) -enclosing_stmt(#23062,#23049) -expr_containers(#23062,#22805) +literals("a","a",#23060) +is_abstract_member(#23058) +#23061=* +typeexprs(#23061,23,#23058,2,"(x: string) => void") +#23062=@"loc,{#10000},91,23,91,41" +locations_default(#23062,#10000,91,23,91,41) +hasLocation(#23061,#23062) +enclosing_stmt(#23061,#23050) +expr_containers(#23061,#22805) #23063=* -scopes(#23063,1) -scopenodes(#23062,#23063) -scopenesting(#23063,#22808) -#23064=@"var;{x};{#23063}" -variables(#23064,"x",#23063) -#23065=* -exprs(#23065,78,#23062,0,"x") -hasLocation(#23065,#21910) -expr_containers(#23065,#23062) -literals("x","x",#23065) -decl(#23065,#23064) -#23066=@"var;{arguments};{#23063}" -variables(#23066,"arguments",#23063) -is_arguments_object(#23066) -#23067=* -typeexprs(#23067,2,#23062,-3,"void") -hasLocation(#23067,#21920) -expr_containers(#23067,#23062) -literals("void","void",#23067) +exprs(#23063,9,#23061,0,"(x: string) => void") +hasLocation(#23063,#23062) +enclosing_stmt(#23063,#23050) +expr_containers(#23063,#22805) +#23064=* +scopes(#23064,1) +scopenodes(#23063,#23064) +scopenesting(#23064,#22808) +#23065=@"var;{x};{#23064}" +variables(#23065,"x",#23064) +#23066=* +exprs(#23066,78,#23063,0,"x") +hasLocation(#23066,#21910) +expr_containers(#23066,#23063) +literals("x","x",#23066) +decl(#23066,#23065) +#23067=@"var;{arguments};{#23064}" +variables(#23067,"arguments",#23064) +is_arguments_object(#23067) #23068=* -typeexprs(#23068,2,#23062,-6,"string") -hasLocation(#23068,#21914) -expr_containers(#23068,#23062) -literals("string","string",#23068) +typeexprs(#23068,2,#23063,-3,"void") +hasLocation(#23068,#21920) +expr_containers(#23068,#23063) +literals("void","void",#23068) #23069=* -properties(#23069,#23055,1,8,"b: (x: ... => void") -#23070=@"loc,{#10000},91,44,91,65" -locations_default(#23070,#10000,91,44,91,65) -hasLocation(#23069,#23070) -#23071=* -exprs(#23071,0,#23069,0,"b") -hasLocation(#23071,#21924) -enclosing_stmt(#23071,#23049) -expr_containers(#23071,#22805) -literals("b","b",#23071) -is_abstract_member(#23069) +typeexprs(#23069,2,#23063,-6,"string") +hasLocation(#23069,#21914) +expr_containers(#23069,#23063) +literals("string","string",#23069) +#23070=* +properties(#23070,#23056,1,8,"b: (x: ... => void") +#23071=@"loc,{#10000},91,44,91,65" +locations_default(#23071,#10000,91,44,91,65) +hasLocation(#23070,#23071) #23072=* -typeexprs(#23072,23,#23069,2,"(x: string) => void") -#23073=@"loc,{#10000},91,47,91,65" -locations_default(#23073,#10000,91,47,91,65) -hasLocation(#23072,#23073) -enclosing_stmt(#23072,#23049) +exprs(#23072,0,#23070,0,"b") +hasLocation(#23072,#21924) +enclosing_stmt(#23072,#23050) expr_containers(#23072,#22805) -#23074=* -exprs(#23074,9,#23072,0,"(x: string) => void") -hasLocation(#23074,#23073) -enclosing_stmt(#23074,#23049) -expr_containers(#23074,#22805) +literals("b","b",#23072) +is_abstract_member(#23070) +#23073=* +typeexprs(#23073,23,#23070,2,"(x: string) => void") +#23074=@"loc,{#10000},91,47,91,65" +locations_default(#23074,#10000,91,47,91,65) +hasLocation(#23073,#23074) +enclosing_stmt(#23073,#23050) +expr_containers(#23073,#22805) #23075=* -scopes(#23075,1) -scopenodes(#23074,#23075) -scopenesting(#23075,#22808) -#23076=@"var;{x};{#23075}" -variables(#23076,"x",#23075) -#23077=* -exprs(#23077,78,#23074,0,"x") -hasLocation(#23077,#21930) -expr_containers(#23077,#23074) -literals("x","x",#23077) -decl(#23077,#23076) -#23078=@"var;{arguments};{#23075}" -variables(#23078,"arguments",#23075) -is_arguments_object(#23078) -#23079=* -typeexprs(#23079,2,#23074,-3,"void") -hasLocation(#23079,#21940) -expr_containers(#23079,#23074) -literals("void","void",#23079) +exprs(#23075,9,#23073,0,"(x: string) => void") +hasLocation(#23075,#23074) +enclosing_stmt(#23075,#23050) +expr_containers(#23075,#22805) +#23076=* +scopes(#23076,1) +scopenodes(#23075,#23076) +scopenesting(#23076,#22808) +#23077=@"var;{x};{#23076}" +variables(#23077,"x",#23076) +#23078=* +exprs(#23078,78,#23075,0,"x") +hasLocation(#23078,#21930) +expr_containers(#23078,#23075) +literals("x","x",#23078) +decl(#23078,#23077) +#23079=@"var;{arguments};{#23076}" +variables(#23079,"arguments",#23076) +is_arguments_object(#23079) #23080=* -typeexprs(#23080,2,#23074,-6,"string") -hasLocation(#23080,#21934) -expr_containers(#23080,#23074) -literals("string","string",#23080) +typeexprs(#23080,2,#23075,-3,"void") +hasLocation(#23080,#21940) +expr_containers(#23080,#23075) +literals("void","void",#23080) #23081=* -stmts(#23081,35,#22805,12,"type T2 ... oid }>;") -#23082=@"loc,{#10000},92,3,92,69" -locations_default(#23082,#10000,92,3,92,69) -hasLocation(#23081,#23082) -stmt_containers(#23081,#22805) -#23083=* -typeexprs(#23083,1,#23081,0,"T21") -hasLocation(#23083,#21950) -enclosing_stmt(#23083,#23081) -expr_containers(#23083,#22805) -literals("T21","T21",#23083) -typedecl(#23083,#22821) +typeexprs(#23081,2,#23075,-6,"string") +hasLocation(#23081,#21934) +expr_containers(#23081,#23075) +literals("string","string",#23081) +#23082=* +stmts(#23082,35,#22805,12,"type T2 ... oid }>;") +#23083=@"loc,{#10000},92,3,92,69" +locations_default(#23083,#10000,92,3,92,69) +hasLocation(#23082,#23083) +stmt_containers(#23082,#22805) #23084=* -typeexprs(#23084,14,#23081,1,"Bar<{ a ... void }>") -#23085=@"loc,{#10000},92,14,92,68" -locations_default(#23085,#10000,92,14,92,68) -hasLocation(#23084,#23085) -enclosing_stmt(#23084,#23081) +typeexprs(#23084,1,#23082,0,"T21") +hasLocation(#23084,#21950) +enclosing_stmt(#23084,#23082) expr_containers(#23084,#22805) -#23086=* -typeexprs(#23086,0,#23084,-1,"Bar") -hasLocation(#23086,#21954) -enclosing_stmt(#23086,#23081) -expr_containers(#23086,#22805) -literals("Bar","Bar",#23086) -typebind(#23086,#22819) +literals("T21","T21",#23084) +typedecl(#23084,#22822) +#23085=* +typeexprs(#23085,14,#23082,1,"Bar<{ a ... void }>") +#23086=@"loc,{#10000},92,14,92,68" +locations_default(#23086,#10000,92,14,92,68) +hasLocation(#23085,#23086) +enclosing_stmt(#23085,#23082) +expr_containers(#23085,#22805) #23087=* -typeexprs(#23087,21,#23084,0,"{ a: (x ... void }") -#23088=@"loc,{#10000},92,18,92,67" -locations_default(#23088,#10000,92,18,92,67) -hasLocation(#23087,#23088) -enclosing_stmt(#23087,#23081) +typeexprs(#23087,0,#23085,-1,"Bar") +hasLocation(#23087,#21954) +enclosing_stmt(#23087,#23082) expr_containers(#23087,#22805) -#23089=* -properties(#23089,#23087,0,8,"a: (x: ... > void,") -#23090=@"loc,{#10000},92,20,92,42" -locations_default(#23090,#10000,92,20,92,42) -hasLocation(#23089,#23090) -#23091=* -exprs(#23091,0,#23089,0,"a") -hasLocation(#23091,#21960) -enclosing_stmt(#23091,#23081) -expr_containers(#23091,#22805) -literals("a","a",#23091) -is_abstract_member(#23089) +literals("Bar","Bar",#23087) +typebind(#23087,#22820) +#23088=* +typeexprs(#23088,21,#23085,0,"{ a: (x ... void }") +#23089=@"loc,{#10000},92,18,92,67" +locations_default(#23089,#10000,92,18,92,67) +hasLocation(#23088,#23089) +enclosing_stmt(#23088,#23082) +expr_containers(#23088,#22805) +#23090=* +properties(#23090,#23088,0,8,"a: (x: ... > void,") +#23091=@"loc,{#10000},92,20,92,42" +locations_default(#23091,#10000,92,20,92,42) +hasLocation(#23090,#23091) #23092=* -typeexprs(#23092,23,#23089,2,"(x: string) => void") -#23093=@"loc,{#10000},92,23,92,41" -locations_default(#23093,#10000,92,23,92,41) -hasLocation(#23092,#23093) -enclosing_stmt(#23092,#23081) +exprs(#23092,0,#23090,0,"a") +hasLocation(#23092,#21960) +enclosing_stmt(#23092,#23082) expr_containers(#23092,#22805) -#23094=* -exprs(#23094,9,#23092,0,"(x: string) => void") -hasLocation(#23094,#23093) -enclosing_stmt(#23094,#23081) -expr_containers(#23094,#22805) +literals("a","a",#23092) +is_abstract_member(#23090) +#23093=* +typeexprs(#23093,23,#23090,2,"(x: string) => void") +#23094=@"loc,{#10000},92,23,92,41" +locations_default(#23094,#10000,92,23,92,41) +hasLocation(#23093,#23094) +enclosing_stmt(#23093,#23082) +expr_containers(#23093,#22805) #23095=* -scopes(#23095,1) -scopenodes(#23094,#23095) -scopenesting(#23095,#22808) -#23096=@"var;{x};{#23095}" -variables(#23096,"x",#23095) -#23097=* -exprs(#23097,78,#23094,0,"x") -hasLocation(#23097,#21966) -expr_containers(#23097,#23094) -literals("x","x",#23097) -decl(#23097,#23096) -#23098=@"var;{arguments};{#23095}" -variables(#23098,"arguments",#23095) -is_arguments_object(#23098) -#23099=* -typeexprs(#23099,2,#23094,-3,"void") -hasLocation(#23099,#21976) -expr_containers(#23099,#23094) -literals("void","void",#23099) +exprs(#23095,9,#23093,0,"(x: string) => void") +hasLocation(#23095,#23094) +enclosing_stmt(#23095,#23082) +expr_containers(#23095,#22805) +#23096=* +scopes(#23096,1) +scopenodes(#23095,#23096) +scopenesting(#23096,#22808) +#23097=@"var;{x};{#23096}" +variables(#23097,"x",#23096) +#23098=* +exprs(#23098,78,#23095,0,"x") +hasLocation(#23098,#21966) +expr_containers(#23098,#23095) +literals("x","x",#23098) +decl(#23098,#23097) +#23099=@"var;{arguments};{#23096}" +variables(#23099,"arguments",#23096) +is_arguments_object(#23099) #23100=* -typeexprs(#23100,2,#23094,-6,"string") -hasLocation(#23100,#21970) -expr_containers(#23100,#23094) -literals("string","string",#23100) +typeexprs(#23100,2,#23095,-3,"void") +hasLocation(#23100,#21976) +expr_containers(#23100,#23095) +literals("void","void",#23100) #23101=* -properties(#23101,#23087,1,8,"b: (x: ... => void") -#23102=@"loc,{#10000},92,44,92,65" -locations_default(#23102,#10000,92,44,92,65) -hasLocation(#23101,#23102) -#23103=* -exprs(#23103,0,#23101,0,"b") -hasLocation(#23103,#21980) -enclosing_stmt(#23103,#23081) -expr_containers(#23103,#22805) -literals("b","b",#23103) -is_abstract_member(#23101) +typeexprs(#23101,2,#23095,-6,"string") +hasLocation(#23101,#21970) +expr_containers(#23101,#23095) +literals("string","string",#23101) +#23102=* +properties(#23102,#23088,1,8,"b: (x: ... => void") +#23103=@"loc,{#10000},92,44,92,65" +locations_default(#23103,#10000,92,44,92,65) +hasLocation(#23102,#23103) #23104=* -typeexprs(#23104,23,#23101,2,"(x: number) => void") -#23105=@"loc,{#10000},92,47,92,65" -locations_default(#23105,#10000,92,47,92,65) -hasLocation(#23104,#23105) -enclosing_stmt(#23104,#23081) +exprs(#23104,0,#23102,0,"b") +hasLocation(#23104,#21980) +enclosing_stmt(#23104,#23082) expr_containers(#23104,#22805) -#23106=* -exprs(#23106,9,#23104,0,"(x: number) => void") -hasLocation(#23106,#23105) -enclosing_stmt(#23106,#23081) -expr_containers(#23106,#22805) +literals("b","b",#23104) +is_abstract_member(#23102) +#23105=* +typeexprs(#23105,23,#23102,2,"(x: number) => void") +#23106=@"loc,{#10000},92,47,92,65" +locations_default(#23106,#10000,92,47,92,65) +hasLocation(#23105,#23106) +enclosing_stmt(#23105,#23082) +expr_containers(#23105,#22805) #23107=* -scopes(#23107,1) -scopenodes(#23106,#23107) -scopenesting(#23107,#22808) -#23108=@"var;{x};{#23107}" -variables(#23108,"x",#23107) -#23109=* -exprs(#23109,78,#23106,0,"x") -hasLocation(#23109,#21986) -expr_containers(#23109,#23106) -literals("x","x",#23109) -decl(#23109,#23108) -#23110=@"var;{arguments};{#23107}" -variables(#23110,"arguments",#23107) -is_arguments_object(#23110) -#23111=* -typeexprs(#23111,2,#23106,-3,"void") -hasLocation(#23111,#21996) -expr_containers(#23111,#23106) -literals("void","void",#23111) +exprs(#23107,9,#23105,0,"(x: number) => void") +hasLocation(#23107,#23106) +enclosing_stmt(#23107,#23082) +expr_containers(#23107,#22805) +#23108=* +scopes(#23108,1) +scopenodes(#23107,#23108) +scopenesting(#23108,#22808) +#23109=@"var;{x};{#23108}" +variables(#23109,"x",#23108) +#23110=* +exprs(#23110,78,#23107,0,"x") +hasLocation(#23110,#21986) +expr_containers(#23110,#23107) +literals("x","x",#23110) +decl(#23110,#23109) +#23111=@"var;{arguments};{#23108}" +variables(#23111,"arguments",#23108) +is_arguments_object(#23111) #23112=* -typeexprs(#23112,2,#23106,-6,"number") -hasLocation(#23112,#21990) -expr_containers(#23112,#23106) -literals("number","number",#23112) +typeexprs(#23112,2,#23107,-3,"void") +hasLocation(#23112,#21996) +expr_containers(#23112,#23107) +literals("void","void",#23112) #23113=* -stmts(#23113,17,#22805,13,"declare ... number;") -#23114=@"loc,{#10000},94,3,94,42" -locations_default(#23114,#10000,94,3,94,42) -hasLocation(#23113,#23114) -stmt_containers(#23113,#22805) -has_declare_keyword(#23113) -#23115=* -exprs(#23115,78,#23113,-1,"foo") -hasLocation(#23115,#22008) -expr_containers(#23115,#23113) -literals("foo","foo",#23115) -#23116=@"var;{foo};{#20000}" -variables(#23116,"foo",#20000) -decl(#23115,#23116) +typeexprs(#23113,2,#23107,-6,"number") +hasLocation(#23113,#21990) +expr_containers(#23113,#23107) +literals("number","number",#23113) +#23114=* +stmts(#23114,17,#22805,13,"declare ... number;") +#23115=@"loc,{#10000},94,3,94,42" +locations_default(#23115,#10000,94,3,94,42) +hasLocation(#23114,#23115) +stmt_containers(#23114,#22805) +has_declare_keyword(#23114) +#23116=* +exprs(#23116,78,#23114,-1,"foo") +hasLocation(#23116,#22008) +expr_containers(#23116,#23114) +literals("foo","foo",#23116) +decl(#23116,#22809) #23117=* scopes(#23117,1) -scopenodes(#23113,#23117) +scopenodes(#23114,#23117) scopenesting(#23117,#22808) #23118=@"var;{x};{#23117}" variables(#23118,"x",#23117) #23119=* -exprs(#23119,78,#23113,0,"x") +exprs(#23119,78,#23114,0,"x") hasLocation(#23119,#22012) -expr_containers(#23119,#23113) +expr_containers(#23119,#23114) literals("x","x",#23119) decl(#23119,#23118) #23120=@"var;{arguments};{#23117}" variables(#23120,"arguments",#23117) is_arguments_object(#23120) #23121=* -typeexprs(#23121,2,#23113,-3,"number") +typeexprs(#23121,2,#23114,-3,"number") hasLocation(#23121,#22022) -expr_containers(#23121,#23113) +expr_containers(#23121,#23114) literals("number","number",#23121) #23122=* -typeexprs(#23122,2,#23113,-6,"string") +typeexprs(#23122,2,#23114,-6,"string") hasLocation(#23122,#22016) -expr_containers(#23122,#23113) +expr_containers(#23122,#23114) literals("string","string",#23122) #23123=* stmts(#23123,17,#22805,14,"declare ... string;") @@ -9757,7 +9757,7 @@ exprs(#23125,78,#23123,-1,"foo") hasLocation(#23125,#22030) expr_containers(#23125,#23123) literals("foo","foo",#23125) -decl(#23125,#23116) +decl(#23125,#22809) #23126=* scopes(#23126,1) scopenodes(#23123,#23126) @@ -9795,7 +9795,7 @@ exprs(#23134,78,#23132,-1,"foo") hasLocation(#23134,#22052) expr_containers(#23134,#23132) literals("foo","foo",#23134) -decl(#23134,#23116) +decl(#23134,#22809) #23135=* scopes(#23135,1) scopenodes(#23132,#23135) @@ -9855,7 +9855,7 @@ hasLocation(#23149,#22080) enclosing_stmt(#23149,#23147) expr_containers(#23149,#22805) literals("T30","T30",#23149) -typedecl(#23149,#22822) +typedecl(#23149,#22823) #23150=* typeexprs(#23150,14,#23147,1,"ReturnT ... of foo>") #23151=@"loc,{#10000},97,14,97,35" @@ -9869,7 +9869,7 @@ hasLocation(#23152,#22084) enclosing_stmt(#23152,#23147) expr_containers(#23152,#22805) literals("ReturnType","ReturnType",#23152) -typebind(#23152,#22824) +typebind(#23152,#22825) #23153=* typeexprs(#23153,16,#23150,0,"typeof foo") #23154=@"loc,{#10000},97,25,97,34" @@ -9883,7 +9883,7 @@ hasLocation(#23155,#22090) enclosing_stmt(#23155,#23147) expr_containers(#23155,#22805) literals("foo","foo",#23155) -bind(#23155,#23116) +bind(#23155,#22809) #23156=* stmts(#23156,35,#22805,17,"type An ... => any;") #23157=@"loc,{#10000},99,3,99,45" @@ -9896,7 +9896,7 @@ hasLocation(#23158,#22098) enclosing_stmt(#23158,#23156) expr_containers(#23158,#22805) literals("AnyFunction","AnyFunction",#23158) -typedecl(#23158,#22823) +typedecl(#23158,#22824) #23159=* typeexprs(#23159,23,#23156,1,"(...arg ... => any") #23160=@"loc,{#10000},99,22,99,44" @@ -9953,7 +9953,7 @@ hasLocation(#23172,#22126) enclosing_stmt(#23172,#23170) expr_containers(#23172,#22805) literals("ReturnType","ReturnType",#23172) -typedecl(#23172,#22824) +typedecl(#23172,#22825) #23173=* scopes(#23173,12) scopenodes(#23170,#23173) @@ -9980,7 +9980,7 @@ hasLocation(#23178,#22134) enclosing_stmt(#23178,#23170) expr_containers(#23178,#22805) literals("AnyFunction","AnyFunction",#23178) -typebind(#23178,#22823) +typebind(#23178,#22824) #23179=* typeexprs(#23179,28,#23170,1,"T exten ... R : any") #23180=@"loc,{#10000},100,44,100,90" @@ -10084,21 +10084,21 @@ successor(#23156,#23170) successor(#23147,#23156) successor(#23132,#23147) successor(#23123,#23132) -successor(#23113,#23123) -successor(#23081,#23113) -successor(#23049,#23081) -successor(#23005,#23049) -successor(#22989,#23005) -successor(#22973,#22989) -successor(#22945,#22973) -successor(#22930,#22945) -successor(#22918,#22930) -successor(#22908,#22918) -successor(#22896,#22908) -successor(#22887,#22896) -successor(#22880,#22887) -successor(#22825,#22880) -successor(#22805,#22825) +successor(#23114,#23123) +successor(#23082,#23114) +successor(#23050,#23082) +successor(#23006,#23050) +successor(#22990,#23006) +successor(#22974,#22990) +successor(#22946,#22974) +successor(#22931,#22946) +successor(#22919,#22931) +successor(#22909,#22919) +successor(#22897,#22909) +successor(#22888,#22897) +successor(#22881,#22888) +successor(#22826,#22881) +successor(#22805,#22826) successor(#22185,#22183) successor(#22777,#22807) successor(#22770,#22777) diff --git a/javascript/extractor/tests/ts/output/trap/declareClass.ts.trap b/javascript/extractor/tests/ts/output/trap/declareClass.ts.trap index 6bc9fb5ffb25..83ada22ef89a 100644 --- a/javascript/extractor/tests/ts/output/trap/declareClass.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/declareClass.ts.trap @@ -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") diff --git a/javascript/extractor/tests/ts/output/trap/functiondecorators.ts.trap b/javascript/extractor/tests/ts/output/trap/functiondecorators.ts.trap index 89cd17604433..00276bb64641 100644 --- a/javascript/extractor/tests/ts/output/trap/functiondecorators.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/functiondecorators.ts.trap @@ -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") diff --git a/javascript/extractor/tests/ts/output/trap/nobody.ts.trap b/javascript/extractor/tests/ts/output/trap/nobody.ts.trap index 44a32603e097..717d79423abd 100644 --- a/javascript/extractor/tests/ts/output/trap/nobody.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/nobody.ts.trap @@ -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") diff --git a/javascript/extractor/tests/ts/output/trap/thisparameter.ts.trap b/javascript/extractor/tests/ts/output/trap/thisparameter.ts.trap index 0e766cf77b99..27b075f05c76 100644 --- a/javascript/extractor/tests/ts/output/trap/thisparameter.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/thisparameter.ts.trap @@ -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") diff --git a/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected b/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected index a6c808c6cbfb..aa1d8b2c81de 100644 --- a/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected +++ b/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -145,4 +145,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 diff --git a/javascript/ql/lib/definitions.qll b/javascript/ql/lib/definitions.qll index 2cc9313d3132..2f1c99b7c606 100644 --- a/javascript/ql/lib/definitions.qll +++ b/javascript/ql/lib/definitions.qll @@ -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)) } diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 3e882251cbf7..3bb04f2686be 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -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()) diff --git a/javascript/ql/lib/semmle/javascript/Closure.qll b/javascript/ql/lib/semmle/javascript/Closure.qll index 40aee266379c..c31698333393 100644 --- a/javascript/ql/lib/semmle/javascript/Closure.qll +++ b/javascript/ql/lib/semmle/javascript/Closure.qll @@ -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 diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index 379403eb0ee7..e7534449f55b 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -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) } diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index 8695c893f815..d7fe610b4f11 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -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() + } } /** diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index 35ba8cfe601a..4a461961f8af 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -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 diff --git a/javascript/ql/lib/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll index 10970a2e8b04..85b7695cd70e 100644 --- a/javascript/ql/lib/semmle/javascript/JSDoc.qll +++ b/javascript/ql/lib/semmle/javascript/JSDoc.qll @@ -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` 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, _) } } diff --git a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll index d10b60b92b5b..318ad2f8873e 100644 --- a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll +++ b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll @@ -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) } } diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index 4be331ed6a50..ab670700c24b 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -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" } } diff --git a/javascript/ql/lib/semmle/javascript/Variables.qll b/javascript/ql/lib/semmle/javascript/Variables.qll index 1eeb735124b5..2f9905f86e17 100644 --- a/javascript/ql/lib/semmle/javascript/Variables.qll +++ b/javascript/ql/lib/semmle/javascript/Variables.qll @@ -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. diff --git a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll index bc80826de5c9..7ab04ad5bd26 100644 --- a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll +++ b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll @@ -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) -} diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index 46801bd1ad7e..df3d0d5ff8ba 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -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) + ) } /** diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll index 06729815e9a4..f861488a046c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll @@ -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, _) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll index 5cf5bf1e48eb..a5af2737c186 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll @@ -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. */ diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll index dd6e1a7d9159..d6bcb9ddd400 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll @@ -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) ) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index c06490b84368..5e9846e9ad55 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -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) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll index 4fad4ae1b059..70beadbfa573 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll @@ -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", "") } } } diff --git a/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll new file mode 100644 index 000000000000..96e72108e2ec --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll @@ -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; + + private module TypeConfig implements TypeResolutionInputSig { + predicate isRelevantVariable(LexicalName var) { var instanceof LocalTypeName } + } + + /** + * Associates nodes with information about types. + */ + module TypeFlow = FlowImpl; + + /** + * 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 { + /** + * 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 { + /** 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 { + /** 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::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) + ) + } +} diff --git a/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll new file mode 100644 index 000000000000..ddf5757a38cc --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll @@ -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::track/1; + + predicate trackType = TypeFlow::TrackNode::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::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 { + 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 { + 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::hasProperty/1; + + /** + * Holds if `value` has a type that is considered untaintable (if actually enforced at runtime). + * + * See `isSanitizingPrimitiveType`. + */ + predicate valueHasSanitizingPrimitiveType = + ValueHasProperty::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::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::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) + ) + } +} diff --git a/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll new file mode 100644 index 000000000000..8f6628278c4f --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll @@ -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 + } +} diff --git a/javascript/ql/src/Expressions/MissingAwait.ql b/javascript/ql/src/Expressions/MissingAwait.ql index d97c006a7bd1..a16d31ee2a57 100644 --- a/javascript/ql/src/Expressions/MissingAwait.ql +++ b/javascript/ql/src/Expressions/MissingAwait.ql @@ -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 } diff --git a/javascript/ql/src/meta/alerts/CallGraph.ql b/javascript/ql/src/meta/alerts/CallGraph.ql index 364d81e32c90..c721e72f6404 100644 --- a/javascript/ql/src/meta/alerts/CallGraph.ql +++ b/javascript/ql/src/meta/alerts/CallGraph.ql @@ -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() diff --git a/javascript/ql/src/meta/types/TypesWithQualifiedName.ql b/javascript/ql/src/meta/types/TypesWithQualifiedName.ql deleted file mode 100644 index db23d2a807ef..000000000000 --- a/javascript/ql/src/meta/types/TypesWithQualifiedName.ql +++ /dev/null @@ -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(_, _)) diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/types.ts b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/types.ts new file mode 100644 index 000000000000..6dd94bcf1952 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/types.ts @@ -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) { + const c = await cp; + /** calls:NS.C.m */ + c.m(); + + cp.then(c2 => { + /** calls:NS.C.m */ + c2.m(); + }) +} diff --git a/javascript/ql/test/library-tests/DataFlow/tests.expected b/javascript/ql/test/library-tests/DataFlow/tests.expected index 55c6771eef02..26ba8c46a993 100644 --- a/javascript/ql/test/library-tests/DataFlow/tests.expected +++ b/javascript/ql/test/library-tests/DataFlow/tests.expected @@ -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 | diff --git a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected index 97730513195b..7c015994aafe 100644 --- a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected +++ b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected @@ -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 | diff --git a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.ql b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.ql index 1b7ebfdd501a..bb1de953169b 100644 --- a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.ql +++ b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.ql @@ -1,3 +1,3 @@ import javascript -query string test_hasQualifiedName(JSDocNamedTypeExpr expr) { expr.hasQualifiedName(result) } +query string test_hasUnderlyingType(JSDocNamedTypeExpr expr) { expr.hasUnderlyingType(result) } diff --git a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected index 8ac3eea2be5f..06afe15ee183 100644 --- a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected +++ b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected @@ -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 | diff --git a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.ql b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.ql index 829435e3220c..fd223ee5a533 100644 --- a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.ql +++ b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.ql @@ -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() } diff --git a/javascript/ql/test/library-tests/TypeAnnotations/TSUnresolvedQualifiedName/QualifiedNames.ql b/javascript/ql/test/library-tests/TypeAnnotations/TSUnresolvedQualifiedName/QualifiedNames.ql index e9d66a4afe09..b4d324377bef 100644 --- a/javascript/ql/test/library-tests/TypeAnnotations/TSUnresolvedQualifiedName/QualifiedNames.ql +++ b/javascript/ql/test/library-tests/TypeAnnotations/TSUnresolvedQualifiedName/QualifiedNames.ql @@ -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 diff --git a/javascript/ql/test/library-tests/TypeScript/Ambients/Ambients.expected b/javascript/ql/test/library-tests/TypeScript/Ambients/Ambients.expected index 7a60484a5f72..63e749e97be8 100644 --- a/javascript/ql/test/library-tests/TypeScript/Ambients/Ambients.expected +++ b/javascript/ql/test/library-tests/TypeScript/Ambients/Ambients.expected @@ -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 | diff --git a/javascript/ql/test/library-tests/TypeScript/CallResolution/CallTarget.expected b/javascript/ql/test/library-tests/TypeScript/CallResolution/CallTarget.expected index a91505e3f034..69374cbf4bf8 100644 --- a/javascript/ql/test/library-tests/TypeScript/CallResolution/CallTarget.expected +++ b/javascript/ql/test/library-tests/TypeScript/CallResolution/CallTarget.expected @@ -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; } | diff --git a/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.expected b/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.expected index 5ee97e2dfb59..3781aea96e20 100644 --- a/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.expected +++ b/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.expected @@ -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 | | 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 | diff --git a/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.ql b/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.ql index 2b63e171f1e9..199749ed3f60 100644 --- a/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.ql +++ b/javascript/ql/test/library-tests/TypeScript/HasQualifiedNameFallback/Test.ql @@ -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") } diff --git a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected index a9123b1ef55b..91eb164f394c 100644 --- a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected +++ b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected @@ -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() | diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/calls.ts b/javascript/ql/test/library-tests/UnderlyingTypes/calls.ts new file mode 100644 index 000000000000..68509e4a1c63 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/calls.ts @@ -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 + ) { } + ); +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/closure.es.js b/javascript/ql/test/library-tests/UnderlyingTypes/closure.es.js new file mode 100644 index 000000000000..cb140ec63c97 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/closure.es.js @@ -0,0 +1,5 @@ +goog.declareModuleId("closure.es") + +const Bar = goog.require('closure.reexported.Bar'); + +export { Bar } diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/closure.lib.js b/javascript/ql/test/library-tests/UnderlyingTypes/closure.lib.js new file mode 100644 index 000000000000..ffd67593202c --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/closure.lib.js @@ -0,0 +1,3 @@ +goog.module("closure.lib") + +exports.Foo = goog.require('closure.reexported.Foo'); diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/closure.use.js b/javascript/ql/test/library-tests/UnderlyingTypes/closure.use.js new file mode 100644 index 000000000000..22fc397cf3d0 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/closure.use.js @@ -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 +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/contextualTypes.ts b/javascript/ql/test/library-tests/UnderlyingTypes/contextualTypes.ts new file mode 100644 index 000000000000..cc461c5c7dda --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/contextualTypes.ts @@ -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 { + return { + handle(req) { // $ hasUnderlyingType='express'.Request + + } + } +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.ts new file mode 100644 index 000000000000..47ef09acc6e5 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.ts @@ -0,0 +1 @@ +export * from 'express'; diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.use.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.use.ts new file mode 100644 index 000000000000..bb94da47faf9 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressBulkExport.use.ts @@ -0,0 +1,7 @@ +import { Request, Response } from './expressBulkExport'; + +function t1(req: Request) { // $ hasUnderlyingType='express'.Request +} + +function t2(res: Response) { // $ hasUnderlyingType='express'.Response +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.ts new file mode 100644 index 000000000000..8aa013bcde09 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.ts @@ -0,0 +1,2 @@ +import E = require('express'); +export = E; diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.use.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.use.ts new file mode 100644 index 000000000000..da65575a443a --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssign.use.ts @@ -0,0 +1,4 @@ +import { Request } from "./expressExportAssign"; + +function t1(req: Request) { // $ hasUnderlyingType='express'.Request +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.ts new file mode 100644 index 000000000000..23c22e445914 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.ts @@ -0,0 +1,5 @@ +import Express = require('express'); +namespace Wrapper { + export import E = Express; +} +export = Wrapper; diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.use.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.use.ts new file mode 100644 index 000000000000..7bcf4b419e95 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressExportAssignWrapper.use.ts @@ -0,0 +1,4 @@ +import { E } from "./expressExportAssignWrapper"; + +function t1(req: E.Request) { // $ hasUnderlyingType='express'.Request +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.ts new file mode 100644 index 000000000000..c8aaf3bb9956 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.ts @@ -0,0 +1,2 @@ +export { Request } from 'express'; +export { Response as R } from 'express'; diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.use.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.use.ts new file mode 100644 index 000000000000..41ce42e3b1fa --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressSelectiveExport.use.ts @@ -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 +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.ts new file mode 100644 index 000000000000..6fae12f06847 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.ts @@ -0,0 +1 @@ +export * as wrapper from 'express'; diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.use.ts b/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.use.ts new file mode 100644 index 000000000000..62f7e519ff0e --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/expressWrapperExport.use.ts @@ -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' +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/generics.ts b/javascript/ql/test/library-tests/UnderlyingTypes/generics.ts new file mode 100644 index 000000000000..26e4499f4da2 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/generics.ts @@ -0,0 +1,46 @@ +import * as express from 'express'; + +type Box1 = { + value: T; + other: string; +}; +function t1(b: Box1) { + b.value; // $ MISSING: hasUnderlyingType='express'.Request + b.other; +} + +interface Box2 { + value: T; + other: string; +} +function t2(b: Box2) { + b.value; // $ MISSING: hasUnderlyingType='express'.Request + b.other; +} + +class Box3 { + value: T; + other: string; +} +function t3(b: Box3) { + b.value; // $ MISSING: hasUnderlyingType='express'.Request + b.other; +} + +abstract class Box4 { + abstract getValue(): T; + abstract getOther(): string; +} +function t4(b: Box4) { + b.getValue(); // $ MISSING: hasUnderlyingType='express'.Request + b.getOther(); +} + +type Box5 = { + value: T & { blah: string }; + other: string; +}; +function t5(b: Box5) { + b.value; // $ MISSING: hasUnderlyingType='express'.Request + b.other; +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/globals.ts b/javascript/ql/test/library-tests/UnderlyingTypes/globals.ts new file mode 100644 index 000000000000..8fc6546c70f3 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/globals.ts @@ -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 +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/jsdoc.js b/javascript/ql/test/library-tests/UnderlyingTypes/jsdoc.js new file mode 100644 index 000000000000..662faeb52c9a --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/jsdoc.js @@ -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 +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/namedImport.ts b/javascript/ql/test/library-tests/UnderlyingTypes/namedImport.ts new file mode 100644 index 000000000000..56b1d43d399d --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/namedImport.ts @@ -0,0 +1,4 @@ +import { Request } from 'express'; + +function t1(req: Request) { // $ hasUnderlyingType='express'.Request +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/namespaceDecls.ts b/javascript/ql/test/library-tests/UnderlyingTypes/namespaceDecls.ts new file mode 100644 index 000000000000..bd8811dfe7aa --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/namespaceDecls.ts @@ -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' +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/namespaceImport.ts b/javascript/ql/test/library-tests/UnderlyingTypes/namespaceImport.ts new file mode 100644 index 000000000000..f2f96865f390 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/namespaceImport.ts @@ -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' +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/props.ts b/javascript/ql/test/library-tests/UnderlyingTypes/props.ts new file mode 100644 index 000000000000..1aded75ae95f --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/props.ts @@ -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; +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/subtype.ts b/javascript/ql/test/library-tests/UnderlyingTypes/subtype.ts new file mode 100644 index 000000000000..a23b85e3b81e --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/subtype.ts @@ -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 +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/test.expected b/javascript/ql/test/library-tests/UnderlyingTypes/test.expected new file mode 100644 index 000000000000..9525a32706b4 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/test.expected @@ -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 | e | 'express'.Request | +| typeCast.ts:6:16:6:42 | e satis ... Request | 'express'.Request | +| varAssignment.ts:4:9:4:11 | req | 'express'.Request | diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/test.ql b/javascript/ql/test/library-tests/UnderlyingTypes/test.ql new file mode 100644 index 000000000000..d3074111f919 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/test.ql @@ -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) + ) +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/test.qlref b/javascript/ql/test/library-tests/UnderlyingTypes/test.qlref new file mode 100644 index 000000000000..ab6773f15f90 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/test.qlref @@ -0,0 +1,2 @@ +query: test.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/tsconfig.json b/javascript/ql/test/library-tests/UnderlyingTypes/tsconfig.json new file mode 100644 index 000000000000..82194fc7ab06 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/tsconfig.json @@ -0,0 +1,3 @@ +{ + "include": ["."] +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/typeCast.ts b/javascript/ql/test/library-tests/UnderlyingTypes/typeCast.ts new file mode 100644 index 000000000000..09b6105d0126 --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/typeCast.ts @@ -0,0 +1,7 @@ +import * as express from 'express'; + +function t1(e) { + var req1 = e as express.Request; // $ hasUnderlyingType='express'.Request + var req2 = e; // $ hasUnderlyingType='express'.Request + var req3 = e satisfies express.Request; // $ hasUnderlyingType='express'.Request +} diff --git a/javascript/ql/test/library-tests/UnderlyingTypes/varAssignment.ts b/javascript/ql/test/library-tests/UnderlyingTypes/varAssignment.ts new file mode 100644 index 000000000000..c7160e16561e --- /dev/null +++ b/javascript/ql/test/library-tests/UnderlyingTypes/varAssignment.ts @@ -0,0 +1,5 @@ +import * as express from 'express'; + +function t1(e) { + var req: express.Request = e; // $ hasUnderlyingType='express'.Request +} diff --git a/javascript/ql/test/library-tests/frameworks/Nest/test.expected b/javascript/ql/test/library-tests/frameworks/Nest/test.expected index ff12967bec69..db49fc95eba9 100644 --- a/javascript/ql/test/library-tests/frameworks/Nest/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Nest/test.expected @@ -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 | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected index 6ba8ab703bff..0f5659492116 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected @@ -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 | '

' | event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '

' | 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 | "
" | jquery.js:2:17:2:40 | documen ... .search | jquery.js:7:5:7:34 | "
" | 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 | "" + ... "" | jquery.js:10:13:10:20 | location | jquery.js:10:5:10:40 | "" + ... "" | 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 | '

' | semmle.label | '

' | | 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 | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 0ed15b8d92ab..c031b7c1810c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -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 | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-any.ts b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-any.ts new file mode 100644 index 000000000000..df8267bba306 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-any.ts @@ -0,0 +1,7 @@ +import 'dummy'; + +declare var $: any; + +function t() { + $(window.name); // $ Alert +} diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-type.ts b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-type.ts new file mode 100644 index 000000000000..c866f71a1eb9 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery-declare-type.ts @@ -0,0 +1,7 @@ +import 'dummy'; + +declare var $: JQueryStatic; + +function t() { + $(window.name); // $ Alert +} diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected index 499cf6cce49d..4f757d1a9313 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected @@ -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>" | 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 diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/typed.ts b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/typed.ts index 1c50460050cf..8c166fb243ff 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/typed.ts +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/typed.ts @@ -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 = "" + s + ""; // $ SPURIOUS: Alert - inserted into document disconnected from the main DOM. + newDoc.body.innerHTML = "" + s + ""; // OK - inserted into document disconnected from the main DOM. } export function id(s: string) { @@ -17,4 +17,3 @@ export function notVulnerable() { const html = "" + s + ""; document.body.innerHTML = html; } - \ No newline at end of file diff --git a/javascript/ql/test/query-tests/definitions/definitions.expected b/javascript/ql/test/query-tests/definitions/definitions.expected index 081db47c3faa..cb91ac6e37ce 100644 --- a/javascript/ql/test/query-tests/definitions/definitions.expected +++ b/javascript/ql/test/query-tests/definitions/definitions.expected @@ -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 | | 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 | | 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 | | 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 | | I |