Skip to content

Commit be27126

Browse files
committed
add support for await using in the JS parser
1 parent 1cbee6a commit be27126

File tree

3 files changed

+125
-23
lines changed

3 files changed

+125
-23
lines changed

javascript/extractor/src/com/semmle/jcorn/Parser.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,17 +2674,29 @@ protected final Statement parseStatement(boolean declaration, boolean topLevel)
26742674
// - 'async /*foo*/ function' is OK.
26752675
// - 'async /*\n*/ function' is invalid.
26762676
boolean isAsyncFunction() {
2677+
return isAsyncKeyword("async", "function");
2678+
}
2679+
2680+
boolean isAwaitUsing() {
2681+
return isAsyncKeyword("await", "using");
2682+
}
2683+
2684+
// check 'pre [no LineTerminator here] keyword'
2685+
// e.g. `await using" or `async function`.
2686+
// is only used for async/await parsing, so it requires ecmaVersion >= 8.
2687+
boolean isAsyncKeyword(String pre, String keyword) {
26772688
if (this.type != TokenType.name
26782689
|| this.options.ecmaVersion() < 8
2679-
|| !this.value.equals("async")) return false;
2690+
|| !this.value.equals(pre)) return false;
26802691

26812692
Matcher m = Whitespace.skipWhiteSpace.matcher(this.input);
26822693
m.find(this.pos);
26832694
int next = m.end();
2695+
int len = keyword.length();
26842696
return !Whitespace.lineBreakG.matcher(inputSubstring(this.pos, next)).matches()
2685-
&& inputSubstring(next, next + 8).equals("function")
2686-
&& (next + 8 == this.input.length()
2687-
|| !Identifiers.isIdentifierChar(this.input.codePointAt(next + 8), false));
2697+
&& inputSubstring(next, next + len).equals(keyword)
2698+
&& (next + len == this.input.length()
2699+
|| !Identifiers.isIdentifierChar(this.input.codePointAt(next + len), false));
26882700
}
26892701

26902702
/**
@@ -2761,6 +2773,10 @@ protected Statement parseStatement(boolean declaration, boolean topLevel, Set<St
27612773
: this.parseExport(startLoc, exports);
27622774

27632775
} else {
2776+
if (this.isAwaitUsing() && (this.inAsync || options.esnext() && !this.inFunction)) {
2777+
this.next();
2778+
return this.parseVarStatement(startLoc, "using");
2779+
}
27642780
if (this.isAsyncFunction() && declaration) {
27652781
this.next();
27662782
return this.parseFunctionStatement(startLoc, true);
@@ -2840,6 +2856,9 @@ protected Statement parseForStatement(Position startLoc) {
28402856
this.expect(TokenType.parenL);
28412857
if (this.type == TokenType.semi) return this.parseFor(startLoc, null);
28422858
boolean isLet = this.isLet();
2859+
if (this.isAwaitUsing() && this.inAsync) {
2860+
this.next(); // just skip the await and treat it as a `using` statement
2861+
}
28432862
if (this.type == TokenType._var || this.type == TokenType._const || isLet || this.type == TokenType._using) {
28442863
Position initStartLoc = this.startLoc;
28452864
String kind = isLet ? "let" : String.valueOf(this.value);
Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
nodes
22
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
3-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | semmle.label | [FunctionDeclStmt] functio ... } } |
4-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | semmle.order | 1 |
3+
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
4+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | semmle.label | [FunctionDeclStmt] functio ... } } |
5+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | semmle.order | 1 |
56
| tst.js:1:10:1:10 | [VarDecl] g | semmle.label | [VarDecl] g |
6-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.label | [BlockStmt] { u ... } } |
7+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | semmle.label | [BlockStmt] { u ... } } |
78
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.label | [DeclStmt] using stream = ... |
89
| tst.js:2:11:2:16 | [VarDecl] stream | semmle.label | [VarDecl] stream |
910
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.label | [VariableDeclarator] stream ... ource() |
@@ -15,26 +16,52 @@ nodes
1516
| tst.js:4:10:4:13 | [VarRef] test | semmle.label | [VarRef] test |
1617
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.label | [AssignExpr] test = 20 |
1718
| tst.js:4:17:4:18 | [Literal] 20 | semmle.label | [Literal] 20 |
18-
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.label | [ForStmt] for (us ... . } |
19+
| tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | semmle.label | [ForStmt] for (us ... ; } |
1920
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.label | [DeclStmt] using stream2 = ... |
2021
| tst.js:6:16:6:22 | [VarDecl] stream2 | semmle.label | [VarDecl] stream2 |
2122
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.label | [VariableDeclarator] stream2 ... ource() |
2223
| tst.js:6:26:6:36 | [VarRef] getResource | semmle.label | [VarRef] getResource |
2324
| tst.js:6:26:6:38 | [CallExpr] getResource() | semmle.label | [CallExpr] getResource() |
24-
| tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.label | [BlockStmt] { ... . } |
25+
| tst.js:6:45:9:5 | [BlockStmt] { ... ; } | semmle.label | [BlockStmt] { ... ; } |
26+
| tst.js:8:9:8:14 | [BreakStmt] break; | semmle.label | [BreakStmt] break; |
27+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | semmle.label | [FunctionDeclStmt] async f ... nd"); } |
28+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | semmle.order | 2 |
29+
| tst.js:12:16:12:16 | [VarDecl] h | semmle.label | [VarDecl] h |
30+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | semmle.label | [BlockStmt] { a ... nd"); } |
31+
| tst.js:13:5:13:39 | [DeclStmt] using stream = ... | semmle.label | [DeclStmt] using stream = ... |
32+
| tst.js:13:17:13:22 | [VarDecl] stream | semmle.label | [VarDecl] stream |
33+
| tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | semmle.label | [VariableDeclarator] stream ... ource() |
34+
| tst.js:13:26:13:36 | [VarRef] getResource | semmle.label | [VarRef] getResource |
35+
| tst.js:13:26:13:38 | [CallExpr] getResource() | semmle.label | [CallExpr] getResource() |
36+
| tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | semmle.label | [ForStmt] for (aw ... ; } |
37+
| tst.js:15:16:15:44 | [DeclStmt] using stream2 = ... | semmle.label | [DeclStmt] using stream2 = ... |
38+
| tst.js:15:22:15:28 | [VarDecl] stream2 | semmle.label | [VarDecl] stream2 |
39+
| tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | semmle.label | [VariableDeclarator] stream2 ... ource() |
40+
| tst.js:15:32:15:42 | [VarRef] getResource | semmle.label | [VarRef] getResource |
41+
| tst.js:15:32:15:44 | [CallExpr] getResource() | semmle.label | [CallExpr] getResource() |
42+
| tst.js:15:51:18:5 | [BlockStmt] { ... ; } | semmle.label | [BlockStmt] { ... ; } |
43+
| tst.js:17:9:17:14 | [BreakStmt] break; | semmle.label | [BreakStmt] break; |
44+
| tst.js:20:5:20:11 | [VarRef] console | semmle.label | [VarRef] console |
45+
| tst.js:20:5:20:15 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
46+
| tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | semmle.label | [MethodCallExpr] console.log("end") |
47+
| tst.js:20:5:20:23 | [ExprStmt] console.log("end"); | semmle.label | [ExprStmt] console.log("end"); |
48+
| tst.js:20:13:20:15 | [Label] log | semmle.label | [Label] log |
49+
| tst.js:20:17:20:21 | [Literal] "end" | semmle.label | [Literal] "end" |
2550
edges
2651
| file://:0:0:0:0 | (Arguments) | tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.label | 0 |
2752
| file://:0:0:0:0 | (Arguments) | tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.order | 0 |
28-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.label | 0 |
29-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.order | 0 |
30-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.label | 5 |
31-
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.order | 5 |
32-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.label | 1 |
33-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.order | 1 |
34-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.label | 2 |
35-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.order | 2 |
36-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.label | 3 |
37-
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.order | 3 |
53+
| file://:0:0:0:0 | (Arguments) | tst.js:20:17:20:21 | [Literal] "end" | semmle.label | 0 |
54+
| file://:0:0:0:0 | (Arguments) | tst.js:20:17:20:21 | [Literal] "end" | semmle.order | 0 |
55+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.label | 0 |
56+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.order | 0 |
57+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:10:1 | [BlockStmt] { u ... } } | semmle.label | 5 |
58+
| tst.js:1:1:10:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:10:1 | [BlockStmt] { u ... } } | semmle.order | 5 |
59+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.label | 1 |
60+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.order | 1 |
61+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.label | 2 |
62+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.order | 2 |
63+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | semmle.label | 3 |
64+
| tst.js:1:14:10:1 | [BlockStmt] { u ... } } | tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | semmle.order | 3 |
3865
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.label | 1 |
3966
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.order | 1 |
4067
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | tst.js:2:11:2:16 | [VarDecl] stream | semmle.label | 1 |
@@ -53,10 +80,10 @@ edges
5380
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:10:4:13 | [VarRef] test | semmle.order | 1 |
5481
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:17:4:18 | [Literal] 20 | semmle.label | 2 |
5582
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:17:4:18 | [Literal] 20 | semmle.order | 2 |
56-
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.label | 1 |
57-
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.order | 1 |
58-
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.label | 2 |
59-
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.order | 2 |
83+
| tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.label | 1 |
84+
| tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.order | 1 |
85+
| tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | tst.js:6:45:9:5 | [BlockStmt] { ... ; } | semmle.label | 2 |
86+
| tst.js:6:5:9:5 | [ForStmt] for (us ... ; } | tst.js:6:45:9:5 | [BlockStmt] { ... ; } | semmle.order | 2 |
6087
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.label | 1 |
6188
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.order | 1 |
6289
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:16:6:22 | [VarDecl] stream2 | semmle.label | 1 |
@@ -65,5 +92,49 @@ edges
6592
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:26:6:38 | [CallExpr] getResource() | semmle.order | 2 |
6693
| tst.js:6:26:6:38 | [CallExpr] getResource() | tst.js:6:26:6:36 | [VarRef] getResource | semmle.label | 0 |
6794
| tst.js:6:26:6:38 | [CallExpr] getResource() | tst.js:6:26:6:36 | [VarRef] getResource | semmle.order | 0 |
95+
| tst.js:6:45:9:5 | [BlockStmt] { ... ; } | tst.js:8:9:8:14 | [BreakStmt] break; | semmle.label | 1 |
96+
| tst.js:6:45:9:5 | [BlockStmt] { ... ; } | tst.js:8:9:8:14 | [BreakStmt] break; | semmle.order | 1 |
97+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | tst.js:12:16:12:16 | [VarDecl] h | semmle.label | 0 |
98+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | tst.js:12:16:12:16 | [VarDecl] h | semmle.order | 0 |
99+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | semmle.label | 5 |
100+
| tst.js:12:1:21:1 | [FunctionDeclStmt] async f ... nd"); } | tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | semmle.order | 5 |
101+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:13:5:13:39 | [DeclStmt] using stream = ... | semmle.label | 1 |
102+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:13:5:13:39 | [DeclStmt] using stream = ... | semmle.order | 1 |
103+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | semmle.label | 2 |
104+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | semmle.order | 2 |
105+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:20:5:20:23 | [ExprStmt] console.log("end"); | semmle.label | 3 |
106+
| tst.js:12:20:21:1 | [BlockStmt] { a ... nd"); } | tst.js:20:5:20:23 | [ExprStmt] console.log("end"); | semmle.order | 3 |
107+
| tst.js:13:5:13:39 | [DeclStmt] using stream = ... | tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | semmle.label | 1 |
108+
| tst.js:13:5:13:39 | [DeclStmt] using stream = ... | tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | semmle.order | 1 |
109+
| tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | tst.js:13:17:13:22 | [VarDecl] stream | semmle.label | 1 |
110+
| tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | tst.js:13:17:13:22 | [VarDecl] stream | semmle.order | 1 |
111+
| tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | tst.js:13:26:13:38 | [CallExpr] getResource() | semmle.label | 2 |
112+
| tst.js:13:17:13:38 | [VariableDeclarator] stream ... ource() | tst.js:13:26:13:38 | [CallExpr] getResource() | semmle.order | 2 |
113+
| tst.js:13:26:13:38 | [CallExpr] getResource() | tst.js:13:26:13:36 | [VarRef] getResource | semmle.label | 0 |
114+
| tst.js:13:26:13:38 | [CallExpr] getResource() | tst.js:13:26:13:36 | [VarRef] getResource | semmle.order | 0 |
115+
| tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | tst.js:15:16:15:44 | [DeclStmt] using stream2 = ... | semmle.label | 1 |
116+
| tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | tst.js:15:16:15:44 | [DeclStmt] using stream2 = ... | semmle.order | 1 |
117+
| tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | tst.js:15:51:18:5 | [BlockStmt] { ... ; } | semmle.label | 2 |
118+
| tst.js:15:5:18:5 | [ForStmt] for (aw ... ; } | tst.js:15:51:18:5 | [BlockStmt] { ... ; } | semmle.order | 2 |
119+
| tst.js:15:16:15:44 | [DeclStmt] using stream2 = ... | tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | semmle.label | 1 |
120+
| tst.js:15:16:15:44 | [DeclStmt] using stream2 = ... | tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | semmle.order | 1 |
121+
| tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | tst.js:15:22:15:28 | [VarDecl] stream2 | semmle.label | 1 |
122+
| tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | tst.js:15:22:15:28 | [VarDecl] stream2 | semmle.order | 1 |
123+
| tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | tst.js:15:32:15:44 | [CallExpr] getResource() | semmle.label | 2 |
124+
| tst.js:15:22:15:44 | [VariableDeclarator] stream2 ... ource() | tst.js:15:32:15:44 | [CallExpr] getResource() | semmle.order | 2 |
125+
| tst.js:15:32:15:44 | [CallExpr] getResource() | tst.js:15:32:15:42 | [VarRef] getResource | semmle.label | 0 |
126+
| tst.js:15:32:15:44 | [CallExpr] getResource() | tst.js:15:32:15:42 | [VarRef] getResource | semmle.order | 0 |
127+
| tst.js:15:51:18:5 | [BlockStmt] { ... ; } | tst.js:17:9:17:14 | [BreakStmt] break; | semmle.label | 1 |
128+
| tst.js:15:51:18:5 | [BlockStmt] { ... ; } | tst.js:17:9:17:14 | [BreakStmt] break; | semmle.order | 1 |
129+
| tst.js:20:5:20:15 | [DotExpr] console.log | tst.js:20:5:20:11 | [VarRef] console | semmle.label | 1 |
130+
| tst.js:20:5:20:15 | [DotExpr] console.log | tst.js:20:5:20:11 | [VarRef] console | semmle.order | 1 |
131+
| tst.js:20:5:20:15 | [DotExpr] console.log | tst.js:20:13:20:15 | [Label] log | semmle.label | 2 |
132+
| tst.js:20:5:20:15 | [DotExpr] console.log | tst.js:20:13:20:15 | [Label] log | semmle.order | 2 |
133+
| tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
134+
| tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
135+
| tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | tst.js:20:5:20:15 | [DotExpr] console.log | semmle.label | 0 |
136+
| tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | tst.js:20:5:20:15 | [DotExpr] console.log | semmle.order | 0 |
137+
| tst.js:20:5:20:23 | [ExprStmt] console.log("end"); | tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | semmle.label | 1 |
138+
| tst.js:20:5:20:23 | [ExprStmt] console.log("end"); | tst.js:20:5:20:22 | [MethodCallExpr] console.log("end") | semmle.order | 1 |
68139
graphProperties
69140
| semmle.graphKind | tree |

javascript/ql/test/library-tests/AST/ExplicitResource/tst.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,17 @@ function g() {
55

66
for (using stream2 = getResource(); ; ) {
77
// ...
8+
break;
89
}
10+
}
11+
12+
async function h() {
13+
await using stream = getResource();
14+
15+
for (await using stream2 = getResource(); ; ) {
16+
// ...
17+
break;
18+
}
19+
20+
console.log("end");
921
}

0 commit comments

Comments
 (0)