From e7f009e8793b550e480de588d690d7cf0750367f Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Thu, 11 Aug 2022 09:53:32 +0200 Subject: [PATCH 1/2] support top-level for await statements --- .../src/com/semmle/jcorn/ESNextParser.java | 6 +- .../src/com/semmle/js/extractor/Main.java | 2 +- .../extractor/tests/esnext/input/for-await.js | 9 + .../esnext/output/trap/for-await.js.trap | 450 ++++++++++++++++++ 4 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 javascript/extractor/tests/esnext/input/for-await.js create mode 100644 javascript/extractor/tests/esnext/output/trap/for-await.js.trap diff --git a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java index 6ad5cca137e..e88f6c2321f 100644 --- a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java @@ -448,7 +448,11 @@ public class ESNextParser extends JSXParser { protected Statement parseForStatement(Position startLoc) { int startPos = this.start; boolean isAwait = false; - if (this.inAsync && this.eatContextual("await")) isAwait = true; + if (this.inAsync || (options.esnext() && !this.inFunction)) { + if (this.eatContextual("await")) { + isAwait = true; + } + } Statement forStmt = super.parseForStatement(startLoc); if (isAwait) { if (forStmt instanceof ForOfStatement) ((ForOfStatement) forStmt).setAwait(true); diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 9929195bb77..6ae1e79dc33 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -41,7 +41,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2022-06-27"; + public static final String EXTRACTOR_VERSION = "2022-07-11"; public static final Pattern NEWLINE = Pattern.compile("\n"); diff --git a/javascript/extractor/tests/esnext/input/for-await.js b/javascript/extractor/tests/esnext/input/for-await.js new file mode 100644 index 00000000000..7440ecce5c9 --- /dev/null +++ b/javascript/extractor/tests/esnext/input/for-await.js @@ -0,0 +1,9 @@ +async function foo() { + for await (const call of calls) { + call(); + } +} + +for await (const call of calls) { + call(); +} \ No newline at end of file diff --git a/javascript/extractor/tests/esnext/output/trap/for-await.js.trap b/javascript/extractor/tests/esnext/output/trap/for-await.js.trap new file mode 100644 index 00000000000..6757b189ce9 --- /dev/null +++ b/javascript/extractor/tests/esnext/output/trap/for-await.js.trap @@ -0,0 +1,450 @@ +#10000=@"/for-await.js;sourcefile" +files(#10000,"/for-await.js") +#10001=@"/;folder" +folders(#10001,"/") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"async function foo() {"," +") +#20003=@"loc,{#10000},1,1,1,22" +locations_default(#20003,#10000,1,1,1,22) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001," for await (const call of calls) {"," +") +#20005=@"loc,{#10000},2,1,2,37" +locations_default(#20005,#10000,2,1,2,37) +hasLocation(#20004,#20005) +indentation(#10000,2," ",4) +#20006=* +lines(#20006,#20001," call(); "," +") +#20007=@"loc,{#10000},3,1,3,19" +locations_default(#20007,#10000,3,1,3,19) +hasLocation(#20006,#20007) +indentation(#10000,3," ",8) +#20008=* +lines(#20008,#20001," }"," +") +#20009=@"loc,{#10000},4,1,4,5" +locations_default(#20009,#10000,4,1,4,5) +hasLocation(#20008,#20009) +indentation(#10000,4," ",4) +#20010=* +lines(#20010,#20001,"}"," +") +#20011=@"loc,{#10000},5,1,5,1" +locations_default(#20011,#10000,5,1,5,1) +hasLocation(#20010,#20011) +#20012=* +lines(#20012,#20001,""," +") +#20013=@"loc,{#10000},6,1,6,0" +locations_default(#20013,#10000,6,1,6,0) +hasLocation(#20012,#20013) +#20014=* +lines(#20014,#20001,"for await (const call of calls) {"," +") +#20015=@"loc,{#10000},7,1,7,33" +locations_default(#20015,#10000,7,1,7,33) +hasLocation(#20014,#20015) +#20016=* +lines(#20016,#20001," call();"," +") +#20017=@"loc,{#10000},8,1,8,11" +locations_default(#20017,#10000,8,1,8,11) +hasLocation(#20016,#20017) +indentation(#10000,8," ",4) +#20018=* +lines(#20018,#20001,"}","") +#20019=@"loc,{#10000},9,1,9,1" +locations_default(#20019,#10000,9,1,9,1) +hasLocation(#20018,#20019) +numlines(#20001,9,8,0) +#20020=* +tokeninfo(#20020,6,#20001,0,"async") +#20021=@"loc,{#10000},1,1,1,5" +locations_default(#20021,#10000,1,1,1,5) +hasLocation(#20020,#20021) +#20022=* +tokeninfo(#20022,7,#20001,1,"function") +#20023=@"loc,{#10000},1,7,1,14" +locations_default(#20023,#10000,1,7,1,14) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,6,#20001,2,"foo") +#20025=@"loc,{#10000},1,16,1,18" +locations_default(#20025,#10000,1,16,1,18) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,8,#20001,3,"(") +#20027=@"loc,{#10000},1,19,1,19" +locations_default(#20027,#10000,1,19,1,19) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,8,#20001,4,")") +#20029=@"loc,{#10000},1,20,1,20" +locations_default(#20029,#10000,1,20,1,20) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,8,#20001,5,"{") +#20031=@"loc,{#10000},1,22,1,22" +locations_default(#20031,#10000,1,22,1,22) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,7,#20001,6,"for") +#20033=@"loc,{#10000},2,5,2,7" +locations_default(#20033,#10000,2,5,2,7) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,6,#20001,7,"await") +#20035=@"loc,{#10000},2,9,2,13" +locations_default(#20035,#10000,2,9,2,13) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,8,"(") +#20037=@"loc,{#10000},2,15,2,15" +locations_default(#20037,#10000,2,15,2,15) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,7,#20001,9,"const") +#20039=@"loc,{#10000},2,16,2,20" +locations_default(#20039,#10000,2,16,2,20) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,6,#20001,10,"call") +#20041=@"loc,{#10000},2,22,2,25" +locations_default(#20041,#10000,2,22,2,25) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,6,#20001,11,"of") +#20043=@"loc,{#10000},2,27,2,28" +locations_default(#20043,#10000,2,27,2,28) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,6,#20001,12,"calls") +#20045=@"loc,{#10000},2,30,2,34" +locations_default(#20045,#10000,2,30,2,34) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,13,")") +#20047=@"loc,{#10000},2,35,2,35" +locations_default(#20047,#10000,2,35,2,35) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,8,#20001,14,"{") +#20049=@"loc,{#10000},2,37,2,37" +locations_default(#20049,#10000,2,37,2,37) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,6,#20001,15,"call") +#20051=@"loc,{#10000},3,9,3,12" +locations_default(#20051,#10000,3,9,3,12) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,8,#20001,16,"(") +#20053=@"loc,{#10000},3,13,3,13" +locations_default(#20053,#10000,3,13,3,13) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20001,17,")") +#20055=@"loc,{#10000},3,14,3,14" +locations_default(#20055,#10000,3,14,3,14) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,8,#20001,18,";") +#20057=@"loc,{#10000},3,15,3,15" +locations_default(#20057,#10000,3,15,3,15) +hasLocation(#20056,#20057) +#20058=* +tokeninfo(#20058,8,#20001,19,"}") +#20059=@"loc,{#10000},4,5,4,5" +locations_default(#20059,#10000,4,5,4,5) +hasLocation(#20058,#20059) +#20060=* +tokeninfo(#20060,8,#20001,20,"}") +hasLocation(#20060,#20011) +#20061=* +tokeninfo(#20061,7,#20001,21,"for") +#20062=@"loc,{#10000},7,1,7,3" +locations_default(#20062,#10000,7,1,7,3) +hasLocation(#20061,#20062) +#20063=* +tokeninfo(#20063,6,#20001,22,"await") +#20064=@"loc,{#10000},7,5,7,9" +locations_default(#20064,#10000,7,5,7,9) +hasLocation(#20063,#20064) +#20065=* +tokeninfo(#20065,8,#20001,23,"(") +#20066=@"loc,{#10000},7,11,7,11" +locations_default(#20066,#10000,7,11,7,11) +hasLocation(#20065,#20066) +#20067=* +tokeninfo(#20067,7,#20001,24,"const") +#20068=@"loc,{#10000},7,12,7,16" +locations_default(#20068,#10000,7,12,7,16) +hasLocation(#20067,#20068) +#20069=* +tokeninfo(#20069,6,#20001,25,"call") +#20070=@"loc,{#10000},7,18,7,21" +locations_default(#20070,#10000,7,18,7,21) +hasLocation(#20069,#20070) +#20071=* +tokeninfo(#20071,6,#20001,26,"of") +#20072=@"loc,{#10000},7,23,7,24" +locations_default(#20072,#10000,7,23,7,24) +hasLocation(#20071,#20072) +#20073=* +tokeninfo(#20073,6,#20001,27,"calls") +#20074=@"loc,{#10000},7,26,7,30" +locations_default(#20074,#10000,7,26,7,30) +hasLocation(#20073,#20074) +#20075=* +tokeninfo(#20075,8,#20001,28,")") +#20076=@"loc,{#10000},7,31,7,31" +locations_default(#20076,#10000,7,31,7,31) +hasLocation(#20075,#20076) +#20077=* +tokeninfo(#20077,8,#20001,29,"{") +#20078=@"loc,{#10000},7,33,7,33" +locations_default(#20078,#10000,7,33,7,33) +hasLocation(#20077,#20078) +#20079=* +tokeninfo(#20079,6,#20001,30,"call") +#20080=@"loc,{#10000},8,5,8,8" +locations_default(#20080,#10000,8,5,8,8) +hasLocation(#20079,#20080) +#20081=* +tokeninfo(#20081,8,#20001,31,"(") +#20082=@"loc,{#10000},8,9,8,9" +locations_default(#20082,#10000,8,9,8,9) +hasLocation(#20081,#20082) +#20083=* +tokeninfo(#20083,8,#20001,32,")") +#20084=@"loc,{#10000},8,10,8,10" +locations_default(#20084,#10000,8,10,8,10) +hasLocation(#20083,#20084) +#20085=* +tokeninfo(#20085,8,#20001,33,";") +#20086=@"loc,{#10000},8,11,8,11" +locations_default(#20086,#10000,8,11,8,11) +hasLocation(#20085,#20086) +#20087=* +tokeninfo(#20087,8,#20001,34,"}") +hasLocation(#20087,#20019) +#20088=* +tokeninfo(#20088,0,#20001,35,"") +#20089=@"loc,{#10000},9,2,9,1" +locations_default(#20089,#10000,9,2,9,1) +hasLocation(#20088,#20089) +toplevels(#20001,0) +#20090=@"loc,{#10000},1,1,9,1" +locations_default(#20090,#10000,1,1,9,1) +hasLocation(#20001,#20090) +#20091=@"var;{foo};{#20000}" +variables(#20091,"foo",#20000) +#20092=* +stmts(#20092,17,#20001,0,"async f ... }\n}") +#20093=@"loc,{#10000},1,1,5,1" +locations_default(#20093,#10000,1,1,5,1) +hasLocation(#20092,#20093) +stmt_containers(#20092,#20001) +#20094=* +exprs(#20094,78,#20092,-1,"foo") +hasLocation(#20094,#20025) +expr_containers(#20094,#20092) +literals("foo","foo",#20094) +decl(#20094,#20091) +#20095=* +scopes(#20095,1) +scopenodes(#20092,#20095) +scopenesting(#20095,#20000) +#20096=@"var;{arguments};{#20095}" +variables(#20096,"arguments",#20095) +is_arguments_object(#20096) +is_async(#20092) +#20097=* +stmts(#20097,1,#20092,-2,"{\n f ... }\n}") +#20098=@"loc,{#10000},1,22,5,1" +locations_default(#20098,#10000,1,22,5,1) +hasLocation(#20097,#20098) +stmt_containers(#20097,#20092) +#20099=* +stmts(#20099,21,#20097,0,"for awa ... \n }") +#20100=@"loc,{#10000},2,5,4,5" +locations_default(#20100,#10000,2,5,4,5) +hasLocation(#20099,#20100) +stmt_containers(#20099,#20092) +#20101=* +exprs(#20101,79,#20099,1,"calls") +hasLocation(#20101,#20045) +enclosing_stmt(#20101,#20099) +expr_containers(#20101,#20092) +literals("calls","calls",#20101) +#20102=@"var;{calls};{#20000}" +variables(#20102,"calls",#20000) +bind(#20101,#20102) +#20103=* +scopes(#20103,6) +scopenodes(#20099,#20103) +scopenesting(#20103,#20095) +#20104=@"var;{call};{#20103}" +variables(#20104,"call",#20103) +#20105=* +stmts(#20105,22,#20099,0,"const call") +#20106=@"loc,{#10000},2,16,2,25" +locations_default(#20106,#10000,2,16,2,25) +hasLocation(#20105,#20106) +stmt_containers(#20105,#20092) +#20107=* +exprs(#20107,64,#20105,0,"call") +hasLocation(#20107,#20041) +enclosing_stmt(#20107,#20105) +expr_containers(#20107,#20092) +#20108=* +exprs(#20108,78,#20107,0,"call") +hasLocation(#20108,#20041) +enclosing_stmt(#20108,#20105) +expr_containers(#20108,#20092) +literals("call","call",#20108) +decl(#20108,#20104) +#20109=* +stmts(#20109,1,#20099,2,"{\n ... \n }") +#20110=@"loc,{#10000},2,37,4,5" +locations_default(#20110,#10000,2,37,4,5) +hasLocation(#20109,#20110) +stmt_containers(#20109,#20092) +#20111=* +stmts(#20111,2,#20109,0,"call();") +#20112=@"loc,{#10000},3,9,3,15" +locations_default(#20112,#10000,3,9,3,15) +hasLocation(#20111,#20112) +stmt_containers(#20111,#20092) +#20113=* +exprs(#20113,13,#20111,0,"call()") +#20114=@"loc,{#10000},3,9,3,14" +locations_default(#20114,#10000,3,9,3,14) +hasLocation(#20113,#20114) +enclosing_stmt(#20113,#20111) +expr_containers(#20113,#20092) +#20115=* +exprs(#20115,79,#20113,-1,"call") +hasLocation(#20115,#20051) +enclosing_stmt(#20115,#20111) +expr_containers(#20115,#20092) +literals("call","call",#20115) +bind(#20115,#20104) +is_for_await_of(#20099) +#20116=* +stmts(#20116,21,#20001,1,"for awa ... ll();\n}") +#20117=@"loc,{#10000},7,1,9,1" +locations_default(#20117,#10000,7,1,9,1) +hasLocation(#20116,#20117) +stmt_containers(#20116,#20001) +#20118=* +exprs(#20118,79,#20116,1,"calls") +hasLocation(#20118,#20074) +enclosing_stmt(#20118,#20116) +expr_containers(#20118,#20001) +literals("calls","calls",#20118) +bind(#20118,#20102) +#20119=* +scopes(#20119,6) +scopenodes(#20116,#20119) +scopenesting(#20119,#20000) +#20120=@"var;{call};{#20119}" +variables(#20120,"call",#20119) +#20121=* +stmts(#20121,22,#20116,0,"const call") +#20122=@"loc,{#10000},7,12,7,21" +locations_default(#20122,#10000,7,12,7,21) +hasLocation(#20121,#20122) +stmt_containers(#20121,#20001) +#20123=* +exprs(#20123,64,#20121,0,"call") +hasLocation(#20123,#20070) +enclosing_stmt(#20123,#20121) +expr_containers(#20123,#20001) +#20124=* +exprs(#20124,78,#20123,0,"call") +hasLocation(#20124,#20070) +enclosing_stmt(#20124,#20121) +expr_containers(#20124,#20001) +literals("call","call",#20124) +decl(#20124,#20120) +#20125=* +stmts(#20125,1,#20116,2,"{\n call();\n}") +#20126=@"loc,{#10000},7,33,9,1" +locations_default(#20126,#10000,7,33,9,1) +hasLocation(#20125,#20126) +stmt_containers(#20125,#20001) +#20127=* +stmts(#20127,2,#20125,0,"call();") +#20128=@"loc,{#10000},8,5,8,11" +locations_default(#20128,#10000,8,5,8,11) +hasLocation(#20127,#20128) +stmt_containers(#20127,#20001) +#20129=* +exprs(#20129,13,#20127,0,"call()") +#20130=@"loc,{#10000},8,5,8,10" +locations_default(#20130,#10000,8,5,8,10) +hasLocation(#20129,#20130) +enclosing_stmt(#20129,#20127) +expr_containers(#20129,#20001) +#20131=* +exprs(#20131,79,#20129,-1,"call") +hasLocation(#20131,#20080) +enclosing_stmt(#20131,#20127) +expr_containers(#20131,#20001) +literals("call","call",#20131) +bind(#20131,#20120) +is_for_await_of(#20116) +#20132=* +entry_cfg_node(#20132,#20001) +#20133=@"loc,{#10000},1,1,1,0" +locations_default(#20133,#10000,1,1,1,0) +hasLocation(#20132,#20133) +#20134=* +exit_cfg_node(#20134,#20001) +hasLocation(#20134,#20089) +successor(#20118,#20116) +successor(#20116,#20121) +successor(#20116,#20134) +successor(#20125,#20127) +successor(#20127,#20131) +successor(#20131,#20129) +successor(#20129,#20116) +successor(#20121,#20124) +successor(#20124,#20123) +successor(#20123,#20125) +successor(#20092,#20118) +#20135=* +entry_cfg_node(#20135,#20092) +hasLocation(#20135,#20133) +#20136=* +exit_cfg_node(#20136,#20092) +#20137=@"loc,{#10000},5,2,5,1" +locations_default(#20137,#10000,5,2,5,1) +hasLocation(#20136,#20137) +successor(#20097,#20101) +successor(#20101,#20099) +successor(#20099,#20105) +successor(#20099,#20136) +successor(#20109,#20111) +successor(#20111,#20115) +successor(#20115,#20113) +successor(#20113,#20099) +successor(#20105,#20108) +successor(#20108,#20107) +successor(#20107,#20109) +successor(#20135,#20097) +successor(#20094,#20092) +successor(#20132,#20094) +numlines(#10000,9,8,0) +filetype(#10000,"javascript") From a28948e836c4136706c9771551fbee1e600d654a Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Mon, 15 Aug 2022 10:53:33 +0200 Subject: [PATCH 2/2] add change note --- javascript/ql/lib/change-notes/2022-08-15-for-await.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2022-08-15-for-await.md diff --git a/javascript/ql/lib/change-notes/2022-08-15-for-await.md b/javascript/ql/lib/change-notes/2022-08-15-for-await.md new file mode 100644 index 00000000000..eb3d1492921 --- /dev/null +++ b/javascript/ql/lib/change-notes/2022-08-15-for-await.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed that top-level `for await` statements would produce a syntax error. These statements are now parsed correctly. \ No newline at end of file