Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Js-parser: add support for for await #1550

Merged
merged 2 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

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

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

# 5.5.2 (2023-12-01) - Lille

Expand Down
4 changes: 4 additions & 0 deletions compiler/lib/javascript.ml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ and statement =
(expression, variable_declaration_kind * for_binding) either
* expression
* (statement * location)
| ForAwaitOf_statement of
(expression, variable_declaration_kind * for_binding) either
* expression
* (statement * location)
| Continue_statement of Label.t option
| Break_statement of Label.t option
| Return_statement of expression option
Expand Down
4 changes: 4 additions & 0 deletions compiler/lib/javascript.mli
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ and statement =
(expression, variable_declaration_kind * for_binding) either
* expression
* (statement * location)
| ForAwaitOf_statement of
(expression, variable_declaration_kind * for_binding) either
* expression
* (statement * location)
| Continue_statement of Label.t option
| Break_statement of Label.t option
| Return_statement of expression option
Expand Down
23 changes: 23 additions & 0 deletions compiler/lib/js_output.ml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ struct
| For_statement (_, _, _, st)
| ForIn_statement (_, _, st) -> ends_with_if_without_else st
| ForOf_statement (_, _, st) -> ends_with_if_without_else st
| ForAwaitOf_statement (_, _, st) -> ends_with_if_without_else st
| If_statement (_, _, None) -> true
| Block _
| Variable_statement _
Expand Down Expand Up @@ -1313,6 +1314,28 @@ struct
PP.end_group f;
statement1 ~last f s;
PP.end_group f
| ForAwaitOf_statement (e1, e2, s) ->
PP.start_group f 0;
PP.start_group f 0;
PP.string f "for await";
PP.break f;
PP.start_group f 1;
PP.string f "(";
(match e1 with
| Left e ->
(* Should not starts with "let" *)
parenthesized_expression ~let_identifier:true Expression f e
| Right (k, v) -> for_binding f k v);
PP.space f;
PP.string f "of";
PP.break f;
PP.space f;
expression Expression f e2;
PP.string f ")";
PP.end_group f;
PP.end_group f;
statement1 ~last f s;
PP.end_group f
| Continue_statement None ->
PP.string f "continue";
last_semi ()
Expand Down
5 changes: 5 additions & 0 deletions compiler/lib/js_parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,11 @@ iteration_stmt:
ForOf_statement (Left left, right, body) }
| T_FOR "(" left=for_single_variable_decl T_OF right=assignment_expr ")" body=stmt
{ ForOf_statement (Right left, right, body) }
| T_FOR T_AWAIT "(" left=left_hand_side_expr T_OF right=assignment_expr ")" body=stmt
{ let left = assignment_target_of_expr None left in
ForAwaitOf_statement (Left left, right, body) }
| T_FOR T_AWAIT "(" left=for_single_variable_decl T_OF right=assignment_expr ")" body=stmt
{ ForAwaitOf_statement (Right left, right, body) }

initializer_no_in:
| "=" e=assignment_expr_no_in { e, p $symbolstartpos }
Expand Down
1 change: 1 addition & 0 deletions compiler/lib/js_simpl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ let rec depth = function
| For_statement (_, _, _, (s, _)) -> depth s + 1
| ForIn_statement (_, _, (s, _)) -> depth s + 1
| ForOf_statement (_, _, (s, _)) -> depth s + 1
| ForAwaitOf_statement (_, _, (s, _)) -> depth s + 1
| Continue_statement _ -> 1
| Break_statement _ -> 1
| Return_statement _ -> 1
Expand Down
37 changes: 35 additions & 2 deletions compiler/lib/js_traverse.ml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ class map : mapper =
| Right (k, d) -> Right (k, m#for_binding k d)
in
ForOf_statement (e1, m#expression e2, (m#statement s, m#loc loc))
| ForAwaitOf_statement (e1, e2, (s, loc)) ->
let e1 =
match e1 with
| Left e -> Left (m#expression e)
| Right (k, d) -> Right (k, m#for_binding k d)
in
ForAwaitOf_statement (e1, m#expression e2, (m#statement s, m#loc loc))
| Continue_statement s -> Continue_statement s
| Break_statement s -> Break_statement s
| Return_statement e -> Return_statement (m#expression_o e)
Expand Down Expand Up @@ -516,7 +523,12 @@ class iter : iterator =
(match e1 with
| Left e -> m#expression e
| Right (k, d) -> m#for_binding k d);

m#expression e2;
m#statement s
| ForAwaitOf_statement (e1, e2, (s, _)) ->
(match e1 with
| Left e -> m#expression e
| Right (k, d) -> m#for_binding k d);
m#expression e2;
m#statement s
| Continue_statement _ -> ()
Expand Down Expand Up @@ -1063,6 +1075,15 @@ class free =
m'#record_block Normal;
m#merge_block_info m';
ForOf_statement (Right (k, l), e2, (st, m#loc loc))
| ForAwaitOf_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
let same_level = level in
let m' = {<state_ = empty; level = same_level>} in
let l = m'#for_binding k l in
let e2 = m'#expression e2 in
let st = m'#statement st in
m'#record_block Normal;
m#merge_block_info m';
ForAwaitOf_statement (Right (k, l), e2, (st, m#loc loc))
| Switch_statement (e, l, def, l') ->
let same_level = level in
let m' = {<state_ = empty; level = same_level>} in
Expand Down Expand Up @@ -1186,6 +1207,10 @@ class rename_variable ~esm =
let m = {<depth = depth + 1>} in
m#for_binding k l;
m#statement st
| _, ForAwaitOf_statement (Right (((Const | Let) as k), l), _e2, (st, _loc)) ->
let m = {<depth = depth + 1>} in
m#for_binding k l;
m#statement st
| _, ForIn_statement (Right (((Const | Let) as k), l), _e2, (st, _loc)) ->
let m = {<depth = depth + 1>} in
m#for_binding k l;
Expand Down Expand Up @@ -1352,10 +1377,17 @@ class rename_variable ~esm =
( Right (k, m'#for_binding k l)
, m'#expression e2
, (m'#statement st, m'#loc loc) )
| ForAwaitOf_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
let ids = bound_idents_of_binding l in
let m' = m#update_state Lexical_block ids [] in
ForAwaitOf_statement
( Right (k, m'#for_binding k l)
, m'#expression e2
, (m'#statement st, m'#loc loc) )
| ForIn_statement (Right (((Const | Let) as k), l), e2, (st, loc)) ->
let ids = bound_idents_of_binding l in
let m' = m#update_state Lexical_block ids [] in
ForOf_statement
ForIn_statement
( Right (k, m'#for_binding k l)
, m'#expression e2
, (m'#statement st, m'#loc loc) )
Expand Down Expand Up @@ -1632,6 +1664,7 @@ class clean =
| For_statement (p1, p2, p3, st) -> For_statement (p1, p2, p3, b st)
| ForIn_statement (param, e, st) -> ForIn_statement (param, e, b st)
| ForOf_statement (param, e, st) -> ForOf_statement (param, e, b st)
| ForAwaitOf_statement (param, e, st) -> ForAwaitOf_statement (param, e, b st)
| Switch_statement (e, l, Some [], []) -> Switch_statement (e, l, None, [])
| s -> s
end
Expand Down
21 changes: 21 additions & 0 deletions compiler/tests-compiler/js_parser_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,27 @@ let%expect_test "assignment pattern" =
/*<<fake:17:4>>*/ for([a, b, {c, d = e, [f]: [g, h, a, i, j]}] of 3)
/*<<fake:17:43>>*/ ; |}]

let%expect_test "for loops" =
(* GH#1017 *)
print
~report:true
~compact:false
{|
for(x in 3);
for(x of 3);
async function f(x) {
for await(x of 3);
}
|};

[%expect
{|
/*<<fake:2:4>>*/ for(x in 3) /*<<fake:2:15>>*/ ;
/*<<fake:3:4>>*/ for(x of 3) /*<<fake:3:15>>*/ ;
/*<<fake:4:4>>*/ async function f(x){
/*<<fake:5:4>>*/ for await(x of 3) /*<<fake:5:21>>*/ ;
/*<<fake:4:4>>*/ } |}]

let%expect_test "string template" =
(* GH#1017 *)
print
Expand Down
27 changes: 26 additions & 1 deletion compiler/tests-compiler/scopes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ let%expect_test "let inside forin" =
1: (function(){
2: let v2 = 2;
3: var v3 = 0, v1 = [1, 2, 3];
4: for(let v4 of v1){console.log(v4); v3 += v1[v4];}
4: for(let v4 in v1){console.log(v4); v3 += v1[v4];}
5: console.log(v3);
6: console.log(v2);
7: }
Expand Down Expand Up @@ -121,6 +121,31 @@ let%expect_test "let inside forof" =
6
2 |}]

let%expect_test "let inside forawaitof" =
test
{|
async function f () {
let x = 2
var y = 0;
for await(let x of [1,2,3]) {
console.log(x);
y += x;
}
console.log(y);
console.log(x);
}
|};
[%expect
{|
$ cat "test.min.js"
1: async function f(){
2: let v1 = 2;
3: var v2 = 0;
4: for await(let v3 of [1, 2, 3]){console.log(v3); v2 += v3;}
5: console.log(v2);
6: console.log(v1);
7: } |}]

let%expect_test "let inside switch" =
test
{|
Expand Down