Skip to content

Commit 9c6b587

Browse files
authored
Js-parser: add support for for await (#1550)
* Compiler: js-parser support for await * Changes
1 parent 94bee37 commit 9c6b587

File tree

9 files changed

+121
-3
lines changed

9 files changed

+121
-3
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
## Features/Changes
44
* Compiler: try to preserve clorures ordering between ml and js
5+
* Compiler: js-parser accept for await
56

67
## Bug fixes
78
* Compiler: js-parser now accept all the line terminators defined in the spec
89
* Compiler: js-parser: fix support for LHS assignment target
910
* Compiler: js-parser: fix parser of default export
1011
* Compiler: js-parser: allow 'as' as ident
12+
* Compiler: js-parser: fix for in rewriting
1113

1214
# 5.5.2 (2023-12-01) - Lille
1315

compiler/lib/javascript.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,10 @@ and statement =
336336
(expression, variable_declaration_kind * for_binding) either
337337
* expression
338338
* (statement * location)
339+
| ForAwaitOf_statement of
340+
(expression, variable_declaration_kind * for_binding) either
341+
* expression
342+
* (statement * location)
339343
| Continue_statement of Label.t option
340344
| Break_statement of Label.t option
341345
| Return_statement of expression option

compiler/lib/javascript.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ and statement =
254254
(expression, variable_declaration_kind * for_binding) either
255255
* expression
256256
* (statement * location)
257+
| ForAwaitOf_statement of
258+
(expression, variable_declaration_kind * for_binding) either
259+
* expression
260+
* (statement * location)
257261
| Continue_statement of Label.t option
258262
| Break_statement of Label.t option
259263
| Return_statement of expression option

compiler/lib/js_output.ml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ struct
275275
| For_statement (_, _, _, st)
276276
| ForIn_statement (_, _, st) -> ends_with_if_without_else st
277277
| ForOf_statement (_, _, st) -> ends_with_if_without_else st
278+
| ForAwaitOf_statement (_, _, st) -> ends_with_if_without_else st
278279
| If_statement (_, _, None) -> true
279280
| Block _
280281
| Variable_statement _
@@ -1313,6 +1314,28 @@ struct
13131314
PP.end_group f;
13141315
statement1 ~last f s;
13151316
PP.end_group f
1317+
| ForAwaitOf_statement (e1, e2, s) ->
1318+
PP.start_group f 0;
1319+
PP.start_group f 0;
1320+
PP.string f "for await";
1321+
PP.break f;
1322+
PP.start_group f 1;
1323+
PP.string f "(";
1324+
(match e1 with
1325+
| Left e ->
1326+
(* Should not starts with "let" *)
1327+
parenthesized_expression ~let_identifier:true Expression f e
1328+
| Right (k, v) -> for_binding f k v);
1329+
PP.space f;
1330+
PP.string f "of";
1331+
PP.break f;
1332+
PP.space f;
1333+
expression Expression f e2;
1334+
PP.string f ")";
1335+
PP.end_group f;
1336+
PP.end_group f;
1337+
statement1 ~last f s;
1338+
PP.end_group f
13161339
| Continue_statement None ->
13171340
PP.string f "continue";
13181341
last_semi ()

compiler/lib/js_parser.mly

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,11 @@ iteration_stmt:
713713
ForOf_statement (Left left, right, body) }
714714
| T_FOR "(" left=for_single_variable_decl T_OF right=assignment_expr ")" body=stmt
715715
{ ForOf_statement (Right left, right, body) }
716+
| T_FOR T_AWAIT "(" left=left_hand_side_expr T_OF right=assignment_expr ")" body=stmt
717+
{ let left = assignment_target_of_expr None left in
718+
ForAwaitOf_statement (Left left, right, body) }
719+
| T_FOR T_AWAIT "(" left=for_single_variable_decl T_OF right=assignment_expr ")" body=stmt
720+
{ ForAwaitOf_statement (Right left, right, body) }
716721

717722
initializer_no_in:
718723
| "=" e=assignment_expr_no_in { e, p $symbolstartpos }

compiler/lib/js_simpl.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ let rec depth = function
160160
| For_statement (_, _, _, (s, _)) -> depth s + 1
161161
| ForIn_statement (_, _, (s, _)) -> depth s + 1
162162
| ForOf_statement (_, _, (s, _)) -> depth s + 1
163+
| ForAwaitOf_statement (_, _, (s, _)) -> depth s + 1
163164
| Continue_statement _ -> 1
164165
| Break_statement _ -> 1
165166
| Return_statement _ -> 1

compiler/lib/js_traverse.ml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ class map : mapper =
176176
| Right (k, d) -> Right (k, m#for_binding k d)
177177
in
178178
ForOf_statement (e1, m#expression e2, (m#statement s, m#loc loc))
179+
| ForAwaitOf_statement (e1, e2, (s, loc)) ->
180+
let e1 =
181+
match e1 with
182+
| Left e -> Left (m#expression e)
183+
| Right (k, d) -> Right (k, m#for_binding k d)
184+
in
185+
ForAwaitOf_statement (e1, m#expression e2, (m#statement s, m#loc loc))
179186
| Continue_statement s -> Continue_statement s
180187
| Break_statement s -> Break_statement s
181188
| Return_statement e -> Return_statement (m#expression_o e)
@@ -516,7 +523,12 @@ class iter : iterator =
516523
(match e1 with
517524
| Left e -> m#expression e
518525
| Right (k, d) -> m#for_binding k d);
519-
526+
m#expression e2;
527+
m#statement s
528+
| ForAwaitOf_statement (e1, e2, (s, _)) ->
529+
(match e1 with
530+
| Left e -> m#expression e
531+
| Right (k, d) -> m#for_binding k d);
520532
m#expression e2;
521533
m#statement s
522534
| Continue_statement _ -> ()
@@ -1063,6 +1075,15 @@ class free =
10631075
m'#record_block Normal;
10641076
m#merge_block_info m';
10651077
ForOf_statement (Right (k, l), e2, (st, m#loc loc))
1078+
| ForAwaitOf_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
1079+
let same_level = level in
1080+
let m' = {<state_ = empty; level = same_level>} in
1081+
let l = m'#for_binding k l in
1082+
let e2 = m'#expression e2 in
1083+
let st = m'#statement st in
1084+
m'#record_block Normal;
1085+
m#merge_block_info m';
1086+
ForAwaitOf_statement (Right (k, l), e2, (st, m#loc loc))
10661087
| Switch_statement (e, l, def, l') ->
10671088
let same_level = level in
10681089
let m' = {<state_ = empty; level = same_level>} in
@@ -1186,6 +1207,10 @@ class rename_variable ~esm =
11861207
let m = {<depth = depth + 1>} in
11871208
m#for_binding k l;
11881209
m#statement st
1210+
| _, ForAwaitOf_statement (Right (((Const | Let) as k), l), _e2, (st, _loc)) ->
1211+
let m = {<depth = depth + 1>} in
1212+
m#for_binding k l;
1213+
m#statement st
11891214
| _, ForIn_statement (Right (((Const | Let) as k), l), _e2, (st, _loc)) ->
11901215
let m = {<depth = depth + 1>} in
11911216
m#for_binding k l;
@@ -1352,10 +1377,17 @@ class rename_variable ~esm =
13521377
( Right (k, m'#for_binding k l)
13531378
, m'#expression e2
13541379
, (m'#statement st, m'#loc loc) )
1380+
| ForAwaitOf_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
1381+
let ids = bound_idents_of_binding l in
1382+
let m' = m#update_state Lexical_block ids [] in
1383+
ForAwaitOf_statement
1384+
( Right (k, m'#for_binding k l)
1385+
, m'#expression e2
1386+
, (m'#statement st, m'#loc loc) )
13551387
| ForIn_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
13561388
let ids = bound_idents_of_binding l in
13571389
let m' = m#update_state Lexical_block ids [] in
1358-
ForOf_statement
1390+
ForIn_statement
13591391
( Right (k, m'#for_binding k l)
13601392
, m'#expression e2
13611393
, (m'#statement st, m'#loc loc) )
@@ -1632,6 +1664,7 @@ class clean =
16321664
| For_statement (p1, p2, p3, st) -> For_statement (p1, p2, p3, b st)
16331665
| ForIn_statement (param, e, st) -> ForIn_statement (param, e, b st)
16341666
| ForOf_statement (param, e, st) -> ForOf_statement (param, e, b st)
1667+
| ForAwaitOf_statement (param, e, st) -> ForAwaitOf_statement (param, e, b st)
16351668
| Switch_statement (e, l, Some [], []) -> Switch_statement (e, l, None, [])
16361669
| s -> s
16371670
end

compiler/tests-compiler/js_parser_printer.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,27 @@ let%expect_test "assignment pattern" =
451451
/*<<fake:17:4>>*/ for([a, b, {c, d = e, [f]: [g, h, a, i, j]}] of 3)
452452
/*<<fake:17:43>>*/ ; |}]
453453

454+
let%expect_test "for loops" =
455+
(* GH#1017 *)
456+
print
457+
~report:true
458+
~compact:false
459+
{|
460+
for(x in 3);
461+
for(x of 3);
462+
async function f(x) {
463+
for await(x of 3);
464+
}
465+
|};
466+
467+
[%expect
468+
{|
469+
/*<<fake:2:4>>*/ for(x in 3) /*<<fake:2:15>>*/ ;
470+
/*<<fake:3:4>>*/ for(x of 3) /*<<fake:3:15>>*/ ;
471+
/*<<fake:4:4>>*/ async function f(x){
472+
/*<<fake:5:4>>*/ for await(x of 3) /*<<fake:5:21>>*/ ;
473+
/*<<fake:4:4>>*/ } |}]
474+
454475
let%expect_test "string template" =
455476
(* GH#1017 *)
456477
print

compiler/tests-compiler/scopes.ml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ let%expect_test "let inside forin" =
7979
1: (function(){
8080
2: let v2 = 2;
8181
3: var v3 = 0, v1 = [1, 2, 3];
82-
4: for(let v4 of v1){console.log(v4); v3 += v1[v4];}
82+
4: for(let v4 in v1){console.log(v4); v3 += v1[v4];}
8383
5: console.log(v3);
8484
6: console.log(v2);
8585
7: }
@@ -121,6 +121,31 @@ let%expect_test "let inside forof" =
121121
6
122122
2 |}]
123123

124+
let%expect_test "let inside forawaitof" =
125+
test
126+
{|
127+
async function f () {
128+
let x = 2
129+
var y = 0;
130+
for await(let x of [1,2,3]) {
131+
console.log(x);
132+
y += x;
133+
}
134+
console.log(y);
135+
console.log(x);
136+
}
137+
|};
138+
[%expect
139+
{|
140+
$ cat "test.min.js"
141+
1: async function f(){
142+
2: let v1 = 2;
143+
3: var v2 = 0;
144+
4: for await(let v3 of [1, 2, 3]){console.log(v3); v2 += v3;}
145+
5: console.log(v2);
146+
6: console.log(v1);
147+
7: } |}]
148+
124149
let%expect_test "let inside switch" =
125150
test
126151
{|

0 commit comments

Comments
 (0)