diff --git a/change-notes/1.23/extractor-javascript.md b/change-notes/1.23/extractor-javascript.md index ed9664ce812f..9d6e89d4b444 100644 --- a/change-notes/1.23/extractor-javascript.md +++ b/change-notes/1.23/extractor-javascript.md @@ -5,3 +5,4 @@ ## Changes to code extraction * Asynchronous generator methods are now parsed correctly and no longer cause a spurious syntax error. +* Top-level `await` is now supported. diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index 59de25a14112..013f8e571810 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -1460,7 +1460,7 @@ protected Expression parseMaybeUnary( int startPos = this.start; Position startLoc = this.startLoc; Expression expr; - if (this.inAsync && this.isContextual("await")) { + if ((this.inAsync || options.esnext() && !this.inFunction) && this.isContextual("await")) { expr = this.parseAwait(); sawUnary = true; } else if (this.type.isPrefix) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 3f4ba8e5a189..2b3d64228e02 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -37,7 +37,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 = "2019-09-04"; + public static final String EXTRACTOR_VERSION = "2019-09-13"; public static final Pattern NEWLINE = Pattern.compile("\n"); @@ -328,7 +328,7 @@ private ArgsParser addArgs(ArgsParser argsParser) { 0, "Enable experimental support for pending ECMAScript proposals " + "(public class fields, function.sent, decorators, export extensions, function bind, " - + "parameter-less catch, dynamic import, numeric separators, bigints), " + + "parameter-less catch, dynamic import, numeric separators, bigints, top-level await), " + "as well as other language extensions (E4X, JScript, Mozilla and v8-specific extensions) and full HTML extraction."); argsParser.addFlag( P_EXTERNS, 0, "Extract the given JavaScript files as Closure-style externs."); diff --git a/javascript/extractor/tests/esnext/input/top-level-await.js b/javascript/extractor/tests/esnext/input/top-level-await.js new file mode 100644 index 000000000000..7162da713627 --- /dev/null +++ b/javascript/extractor/tests/esnext/input/top-level-await.js @@ -0,0 +1,2 @@ +import { language } from 'settings'; +const strings = await import(`./i18n/${language}`); diff --git a/javascript/extractor/tests/esnext/output/trap/top-level-await.js.trap b/javascript/extractor/tests/esnext/output/trap/top-level-await.js.trap new file mode 100644 index 000000000000..0092442a55ad --- /dev/null +++ b/javascript/extractor/tests/esnext/output/trap/top-level-await.js.trap @@ -0,0 +1,263 @@ +#10000=@"/top-level-await.js;sourcefile" +files(#10000,"/top-level-await.js","top-level-await","js",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"import { language } from 'settings';"," +") +#20003=@"loc,{#10000},1,1,1,36" +locations_default(#20003,#10000,1,1,1,36) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001,"const strings = await import(`./i18n/${language}`);"," +") +#20005=@"loc,{#10000},2,1,2,51" +locations_default(#20005,#10000,2,1,2,51) +hasLocation(#20004,#20005) +numlines(#20001,2,2,0) +#20006=* +tokeninfo(#20006,7,#20001,0,"import") +#20007=@"loc,{#10000},1,1,1,6" +locations_default(#20007,#10000,1,1,1,6) +hasLocation(#20006,#20007) +#20008=* +tokeninfo(#20008,8,#20001,1,"{") +#20009=@"loc,{#10000},1,8,1,8" +locations_default(#20009,#10000,1,8,1,8) +hasLocation(#20008,#20009) +#20010=* +tokeninfo(#20010,6,#20001,2,"language") +#20011=@"loc,{#10000},1,10,1,17" +locations_default(#20011,#10000,1,10,1,17) +hasLocation(#20010,#20011) +#20012=* +tokeninfo(#20012,8,#20001,3,"}") +#20013=@"loc,{#10000},1,19,1,19" +locations_default(#20013,#10000,1,19,1,19) +hasLocation(#20012,#20013) +#20014=* +tokeninfo(#20014,6,#20001,4,"from") +#20015=@"loc,{#10000},1,21,1,24" +locations_default(#20015,#10000,1,21,1,24) +hasLocation(#20014,#20015) +#20016=* +tokeninfo(#20016,4,#20001,5,"'settings'") +#20017=@"loc,{#10000},1,26,1,35" +locations_default(#20017,#10000,1,26,1,35) +hasLocation(#20016,#20017) +#20018=* +tokeninfo(#20018,8,#20001,6,";") +#20019=@"loc,{#10000},1,36,1,36" +locations_default(#20019,#10000,1,36,1,36) +hasLocation(#20018,#20019) +#20020=* +tokeninfo(#20020,7,#20001,7,"const") +#20021=@"loc,{#10000},2,1,2,5" +locations_default(#20021,#10000,2,1,2,5) +hasLocation(#20020,#20021) +#20022=* +tokeninfo(#20022,6,#20001,8,"strings") +#20023=@"loc,{#10000},2,7,2,13" +locations_default(#20023,#10000,2,7,2,13) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,8,#20001,9,"=") +#20025=@"loc,{#10000},2,15,2,15" +locations_default(#20025,#10000,2,15,2,15) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,6,#20001,10,"await") +#20027=@"loc,{#10000},2,17,2,21" +locations_default(#20027,#10000,2,17,2,21) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,7,#20001,11,"import") +#20029=@"loc,{#10000},2,23,2,28" +locations_default(#20029,#10000,2,23,2,28) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,8,#20001,12,"(") +#20031=@"loc,{#10000},2,29,2,29" +locations_default(#20031,#10000,2,29,2,29) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,8,#20001,13,"`") +#20033=@"loc,{#10000},2,30,2,30" +locations_default(#20033,#10000,2,30,2,30) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,4,#20001,14,"./i18n/") +#20035=@"loc,{#10000},2,31,2,37" +locations_default(#20035,#10000,2,31,2,37) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,15,"${") +#20037=@"loc,{#10000},2,38,2,39" +locations_default(#20037,#10000,2,38,2,39) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,6,#20001,16,"language") +#20039=@"loc,{#10000},2,40,2,47" +locations_default(#20039,#10000,2,40,2,47) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,8,#20001,17,"}") +#20041=@"loc,{#10000},2,48,2,48" +locations_default(#20041,#10000,2,48,2,48) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,4,#20001,18,"") +#20043=@"loc,{#10000},2,49,2,48" +locations_default(#20043,#10000,2,49,2,48) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,8,#20001,19,"`") +#20045=@"loc,{#10000},2,49,2,49" +locations_default(#20045,#10000,2,49,2,49) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,20,")") +#20047=@"loc,{#10000},2,50,2,50" +locations_default(#20047,#10000,2,50,2,50) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,8,#20001,21,";") +#20049=@"loc,{#10000},2,51,2,51" +locations_default(#20049,#10000,2,51,2,51) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,0,#20001,22,"") +#20051=@"loc,{#10000},3,1,3,0" +locations_default(#20051,#10000,3,1,3,0) +hasLocation(#20050,#20051) +toplevels(#20001,0) +#20052=@"loc,{#10000},1,1,3,0" +locations_default(#20052,#10000,1,1,3,0) +hasLocation(#20001,#20052) +#20053=@"module;{#10000},1,1" +scopes(#20053,3) +scopenodes(#20001,#20053) +scopenesting(#20053,#20000) +isModule(#20001) +isES2015Module(#20001) +#20054=@"var;{language};{#20053}" +variables(#20054,"language",#20053) +#20055=@"local_type_name;{language};{#20053}" +local_type_names(#20055,"language",#20053) +#20056=@"local_namespace_name;{language};{#20053}" +local_namespace_names(#20056,"language",#20053) +variables(#20054,"language",#20053) +#20057=@"var;{strings};{#20053}" +variables(#20057,"strings",#20053) +local_type_names(#20055,"language",#20053) +local_namespace_names(#20056,"language",#20053) +#20058=* +stmts(#20058,27,#20001,0,"import ... tings';") +hasLocation(#20058,#20003) +stmtContainers(#20058,#20001) +#20059=* +exprs(#20059,4,#20058,-1,"'settings'") +hasLocation(#20059,#20017) +enclosingStmt(#20059,#20058) +exprContainers(#20059,#20001) +literals("settings","'settings'",#20059) +#20060=* +exprs(#20060,83,#20058,0,"language") +hasLocation(#20060,#20011) +enclosingStmt(#20060,#20058) +exprContainers(#20060,#20001) +#20061=* +exprs(#20061,0,#20060,0,"language") +hasLocation(#20061,#20011) +enclosingStmt(#20061,#20058) +exprContainers(#20061,#20001) +literals("language","language",#20061) +#20062=* +exprs(#20062,78,#20060,1,"language") +hasLocation(#20062,#20011) +enclosingStmt(#20062,#20058) +exprContainers(#20062,#20001) +literals("language","language",#20062) +decl(#20062,#20054) +typedecl(#20062,#20055) +namespacedecl(#20062,#20056) +#20063=* +stmts(#20063,22,#20001,1,"const s ... age}`);") +hasLocation(#20063,#20005) +stmtContainers(#20063,#20001) +#20064=* +exprs(#20064,64,#20063,0,"strings ... uage}`)") +#20065=@"loc,{#10000},2,7,2,50" +locations_default(#20065,#10000,2,7,2,50) +hasLocation(#20064,#20065) +enclosingStmt(#20064,#20063) +exprContainers(#20064,#20001) +#20066=* +exprs(#20066,78,#20064,0,"strings") +hasLocation(#20066,#20023) +enclosingStmt(#20066,#20063) +exprContainers(#20066,#20001) +literals("strings","strings",#20066) +decl(#20066,#20057) +#20067=* +exprs(#20067,92,#20064,1,"await i ... uage}`)") +#20068=@"loc,{#10000},2,17,2,50" +locations_default(#20068,#10000,2,17,2,50) +hasLocation(#20067,#20068) +enclosingStmt(#20067,#20063) +exprContainers(#20067,#20001) +#20069=* +exprs(#20069,99,#20067,0,"import( ... uage}`)") +#20070=@"loc,{#10000},2,23,2,50" +locations_default(#20070,#10000,2,23,2,50) +hasLocation(#20069,#20070) +enclosingStmt(#20069,#20063) +exprContainers(#20069,#20001) +#20071=* +exprs(#20071,71,#20069,0,"`./i18n/${language}`") +#20072=@"loc,{#10000},2,30,2,49" +locations_default(#20072,#10000,2,30,2,49) +hasLocation(#20071,#20072) +enclosingStmt(#20071,#20063) +exprContainers(#20071,#20001) +#20073=* +exprs(#20073,72,#20071,0,"./i18n/") +hasLocation(#20073,#20035) +enclosingStmt(#20073,#20063) +exprContainers(#20073,#20001) +literals("./i18n/","./i18n/",#20073) +#20074=* +exprs(#20074,79,#20071,1,"language") +hasLocation(#20074,#20039) +enclosingStmt(#20074,#20063) +exprContainers(#20074,#20001) +literals("language","language",#20074) +bind(#20074,#20054) +#20075=* +entry_cfg_node(#20075,#20001) +#20076=@"loc,{#10000},1,1,1,0" +locations_default(#20076,#10000,1,1,1,0) +hasLocation(#20075,#20076) +#20077=* +exit_cfg_node(#20077,#20001) +hasLocation(#20077,#20051) +successor(#20063,#20066) +successor(#20071,#20073) +successor(#20074,#20069) +successor(#20073,#20074) +successor(#20069,#20067) +successor(#20067,#20064) +successor(#20066,#20071) +successor(#20064,#20077) +successor(#20058,#20063) +successor(#20060,#20058) +successor(#20075,#20060) +numlines(#10000,2,2,0) +filetype(#10000,"javascript")