From 114c6567ef4233c144727a1a67038a4d8d7990dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 13:50:45 +0900 Subject: [PATCH 01/10] Add tests --- crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts | 1 + crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx | 1 + 2 files changed, 2 insertions(+) create mode 100644 crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts create mode 100644 crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx diff --git a/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts b/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts new file mode 100644 index 000000000000..d1e85649e624 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts @@ -0,0 +1 @@ +console.log(x < y >>> z); diff --git a/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx b/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx new file mode 100644 index 000000000000..d1e85649e624 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx @@ -0,0 +1 @@ +console.log(x < y >>> z); From ab5973fb94a718aedaa5c084af2c01fc8c83ac1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:03:55 +0900 Subject: [PATCH 02/10] Add a test --- crates/swc/tests/fixture/issues-6xxx/6739/input/index.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 crates/swc/tests/fixture/issues-6xxx/6739/input/index.js diff --git a/crates/swc/tests/fixture/issues-6xxx/6739/input/index.js b/crates/swc/tests/fixture/issues-6xxx/6739/input/index.js new file mode 100644 index 000000000000..d1e85649e624 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6739/input/index.js @@ -0,0 +1 @@ +console.log(x < y >>> z); From 593c335f81434720dbe5166af765e20cfdaab130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:08:09 +0900 Subject: [PATCH 03/10] Update test refs --- crates/swc/tests/fixture/issues-6xxx/6739/output/index.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 crates/swc/tests/fixture/issues-6xxx/6739/output/index.js diff --git a/crates/swc/tests/fixture/issues-6xxx/6739/output/index.js b/crates/swc/tests/fixture/issues-6xxx/6739/output/index.js new file mode 100644 index 000000000000..d1e85649e624 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6739/output/index.js @@ -0,0 +1 @@ +console.log(x < y >>> z); From d2d0ed13b27ac53eb93276a9ed9c6270627cbc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:15:49 +0900 Subject: [PATCH 04/10] Update test refs --- .../tests/typescript/issue-6739/1.ts.json | 109 ++++++++++++++++++ .../tests/typescript/issue-6739/2.tsx.json | 109 ++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts.json create mode 100644 crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx.json diff --git a/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts.json b/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts.json new file mode 100644 index 000000000000..07cf524f3a85 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript/issue-6739/1.ts.json @@ -0,0 +1,109 @@ +{ + "type": "Script", + "span": { + "start": 1, + "end": 26, + "ctxt": 0 + }, + "body": [ + { + "type": "ExpressionStatement", + "span": { + "start": 1, + "end": 26, + "ctxt": 0 + }, + "expression": { + "type": "CallExpression", + "span": { + "start": 1, + "end": 25, + "ctxt": 0 + }, + "callee": { + "type": "MemberExpression", + "span": { + "start": 1, + "end": 12, + "ctxt": 0 + }, + "object": { + "type": "Identifier", + "span": { + "start": 1, + "end": 8, + "ctxt": 0 + }, + "value": "console", + "optional": false + }, + "property": { + "type": "Identifier", + "span": { + "start": 9, + "end": 12, + "ctxt": 0 + }, + "value": "log", + "optional": false + } + }, + "arguments": [ + { + "spread": null, + "expression": { + "type": "BinaryExpression", + "span": { + "start": 13, + "end": 24, + "ctxt": 0 + }, + "operator": "<", + "left": { + "type": "Identifier", + "span": { + "start": 13, + "end": 14, + "ctxt": 0 + }, + "value": "x", + "optional": false + }, + "right": { + "type": "BinaryExpression", + "span": { + "start": 17, + "end": 24, + "ctxt": 0 + }, + "operator": ">>>", + "left": { + "type": "Identifier", + "span": { + "start": 17, + "end": 18, + "ctxt": 0 + }, + "value": "y", + "optional": false + }, + "right": { + "type": "Identifier", + "span": { + "start": 23, + "end": 24, + "ctxt": 0 + }, + "value": "z", + "optional": false + } + } + } + } + ], + "typeArguments": null + } + } + ], + "interpreter": null +} diff --git a/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx.json b/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx.json new file mode 100644 index 000000000000..07cf524f3a85 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript/issue-6739/2.tsx.json @@ -0,0 +1,109 @@ +{ + "type": "Script", + "span": { + "start": 1, + "end": 26, + "ctxt": 0 + }, + "body": [ + { + "type": "ExpressionStatement", + "span": { + "start": 1, + "end": 26, + "ctxt": 0 + }, + "expression": { + "type": "CallExpression", + "span": { + "start": 1, + "end": 25, + "ctxt": 0 + }, + "callee": { + "type": "MemberExpression", + "span": { + "start": 1, + "end": 12, + "ctxt": 0 + }, + "object": { + "type": "Identifier", + "span": { + "start": 1, + "end": 8, + "ctxt": 0 + }, + "value": "console", + "optional": false + }, + "property": { + "type": "Identifier", + "span": { + "start": 9, + "end": 12, + "ctxt": 0 + }, + "value": "log", + "optional": false + } + }, + "arguments": [ + { + "spread": null, + "expression": { + "type": "BinaryExpression", + "span": { + "start": 13, + "end": 24, + "ctxt": 0 + }, + "operator": "<", + "left": { + "type": "Identifier", + "span": { + "start": 13, + "end": 14, + "ctxt": 0 + }, + "value": "x", + "optional": false + }, + "right": { + "type": "BinaryExpression", + "span": { + "start": 17, + "end": 24, + "ctxt": 0 + }, + "operator": ">>>", + "left": { + "type": "Identifier", + "span": { + "start": 17, + "end": 18, + "ctxt": 0 + }, + "value": "y", + "optional": false + }, + "right": { + "type": "Identifier", + "span": { + "start": 23, + "end": 24, + "ctxt": 0 + }, + "value": "z", + "optional": false + } + } + } + } + ], + "typeArguments": null + } + } + ], + "interpreter": null +} From c7cf5922f3ae43161a5b60f489317ab9d686f1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:22:42 +0900 Subject: [PATCH 05/10] Fix lexer --- crates/swc_ecma_parser/src/lexer/state.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/swc_ecma_parser/src/lexer/state.rs b/crates/swc_ecma_parser/src/lexer/state.rs index 3f588eda7686..4becd5d22363 100644 --- a/crates/swc_ecma_parser/src/lexer/state.rs +++ b/crates/swc_ecma_parser/src/lexer/state.rs @@ -329,7 +329,9 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> { if c == '<' { self.input.bump(); return Ok(Some(tok!('<'))); - } else if c == '>' { + } else if c == '>' + && (!self.state.is_expr_allowed || self.input.peek() != Some('>')) + { self.input.bump(); return Ok(Some(tok!('>'))); } From 127e3fad6435bcb7682c7fcc497a37114ce7f77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:30:10 +0900 Subject: [PATCH 06/10] Fix --- crates/swc_ecma_parser/src/lexer/state.rs | 3 ++- crates/swc_ecma_parser/src/lib.rs | 4 ++++ crates/swc_ecma_parser/src/parser/typescript.rs | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/swc_ecma_parser/src/lexer/state.rs b/crates/swc_ecma_parser/src/lexer/state.rs index 4becd5d22363..0c0b7eb12b1a 100644 --- a/crates/swc_ecma_parser/src/lexer/state.rs +++ b/crates/swc_ecma_parser/src/lexer/state.rs @@ -330,7 +330,8 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> { self.input.bump(); return Ok(Some(tok!('<'))); } else if c == '>' - && (!self.state.is_expr_allowed || self.input.peek() != Some('>')) + && !self.ctx.prefer_bin_op_over_type_arg_closing + && !(self.state.is_expr_allowed || self.input.peek() != Some('>')) { self.input.bump(); return Ok(Some(tok!('>'))); diff --git a/crates/swc_ecma_parser/src/lib.rs b/crates/swc_ecma_parser/src/lib.rs index 03ec34504ff9..b523edfabb70 100644 --- a/crates/swc_ecma_parser/src/lib.rs +++ b/crates/swc_ecma_parser/src/lib.rs @@ -375,6 +375,10 @@ pub struct Context { ignore_else_clause: bool, disallow_conditional_types: bool, + + /// Used for parsing `>`. If true, `>>` and `>>>` are parsed as binary + /// operators. + prefer_bin_op_over_type_arg_closing: bool, } #[derive(Debug, Clone, Copy, Default)] diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index 4a4c990120b1..70965116ff86 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -557,7 +557,11 @@ impl Parser { pub(super) fn try_parse_ts_type_args(&mut self) -> Option> { debug_assert!(self.input.syntax().typescript()); - self.try_parse_ts(|p| { + self.with_ctx(Context { + prefer_bin_op_over_type_arg_closing: true, + ..self.ctx() + }) + .try_parse_ts(|p| { let type_args = p.parse_ts_type_args()?; if is_one_of!( p, '<', // invalid syntax From 5ef34b0d55cc6be6c6719d139633acced2582fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:55:50 +0900 Subject: [PATCH 07/10] Harden --- crates/swc/tests/fixture/issues-6xxx/6739/input/.swcrc | 8 ++++++++ .../fixture/issues-6xxx/6739/input/{index.js => index.ts} | 0 2 files changed, 8 insertions(+) create mode 100644 crates/swc/tests/fixture/issues-6xxx/6739/input/.swcrc rename crates/swc/tests/fixture/issues-6xxx/6739/input/{index.js => index.ts} (100%) diff --git a/crates/swc/tests/fixture/issues-6xxx/6739/input/.swcrc b/crates/swc/tests/fixture/issues-6xxx/6739/input/.swcrc new file mode 100644 index 000000000000..9381cfabfff4 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6739/input/.swcrc @@ -0,0 +1,8 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": false + } + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6739/input/index.js b/crates/swc/tests/fixture/issues-6xxx/6739/input/index.ts similarity index 100% rename from crates/swc/tests/fixture/issues-6xxx/6739/input/index.js rename to crates/swc/tests/fixture/issues-6xxx/6739/input/index.ts From 0cc308c7a83ea24531c7cf34df012911930e22a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:56:03 +0900 Subject: [PATCH 08/10] Update test refs --- crates/swc/tests/fixture/issues-6xxx/6739/output/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 crates/swc/tests/fixture/issues-6xxx/6739/output/index.ts diff --git a/crates/swc/tests/fixture/issues-6xxx/6739/output/index.ts b/crates/swc/tests/fixture/issues-6xxx/6739/output/index.ts new file mode 100644 index 000000000000..d1e85649e624 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6739/output/index.ts @@ -0,0 +1 @@ +console.log(x < y >>> z); From 663732ace14f8785a5f0d61eb649e984b7670821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 14:59:41 +0900 Subject: [PATCH 09/10] Real fix --- crates/swc_ecma_parser/src/lexer/state.rs | 5 +---- crates/swc_ecma_parser/src/parser/expr.rs | 6 +++++- crates/swc_ecma_parser/src/parser/typescript.rs | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/crates/swc_ecma_parser/src/lexer/state.rs b/crates/swc_ecma_parser/src/lexer/state.rs index 0c0b7eb12b1a..4cf9fb7e523b 100644 --- a/crates/swc_ecma_parser/src/lexer/state.rs +++ b/crates/swc_ecma_parser/src/lexer/state.rs @@ -329,10 +329,7 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> { if c == '<' { self.input.bump(); return Ok(Some(tok!('<'))); - } else if c == '>' - && !self.ctx.prefer_bin_op_over_type_arg_closing - && !(self.state.is_expr_allowed || self.input.peek() != Some('>')) - { + } else if c == '>' && !self.ctx.prefer_bin_op_over_type_arg_closing { self.input.bump(); return Ok(Some(tok!('>'))); } diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index c528113cbc24..3ad445d9c87a 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -671,7 +671,11 @@ impl Parser { return_if_arrow!(self, obj); let type_args = if self.syntax().typescript() && is!(self, '<') { - self.try_parse_ts_type_args() + self.with_ctx(Context { + prefer_bin_op_over_type_arg_closing: true, + ..self.ctx() + }) + .try_parse_ts_type_args() } else { None }; diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index 70965116ff86..4a4c990120b1 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -557,11 +557,7 @@ impl Parser { pub(super) fn try_parse_ts_type_args(&mut self) -> Option> { debug_assert!(self.input.syntax().typescript()); - self.with_ctx(Context { - prefer_bin_op_over_type_arg_closing: true, - ..self.ctx() - }) - .try_parse_ts(|p| { + self.try_parse_ts(|p| { let type_args = p.parse_ts_type_args()?; if is_one_of!( p, '<', // invalid syntax From 19465dc88906006900d2ed92fa7f327165c9386c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 4 Jan 2023 15:00:56 +0900 Subject: [PATCH 10/10] fixup --- crates/swc_ecma_parser/src/parser/typescript.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index 4a4c990120b1..70965116ff86 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -557,7 +557,11 @@ impl Parser { pub(super) fn try_parse_ts_type_args(&mut self) -> Option> { debug_assert!(self.input.syntax().typescript()); - self.try_parse_ts(|p| { + self.with_ctx(Context { + prefer_bin_op_over_type_arg_closing: true, + ..self.ctx() + }) + .try_parse_ts(|p| { let type_args = p.parse_ts_type_args()?; if is_one_of!( p, '<', // invalid syntax