Repository: swc-project/swc (rust)

Issue:
Infinite loop when JSX code is in `.js` file
### Describe the bug

`swc` runs into an infinite loop when trying to parse a js file that contains jsx syntax, but isn't told to parse it as jsx.

Steps to reproduce:

1. Create a `file.js` file and paste the following contents:
  ```jsx
  const a = (
	<section>
		<a href="/foo">foo</a>
	</section>
  );
  ```
2. Run `npx swc ./file.js` -> Infinite loop

### Input code

```jsx
const a = (
	<section>
		<a href="/foo">foo</a>
	</section>
);
```


### Config

```json
none, whatever `npx swc` uses by default.
```


### Playground link

Not possible because the infinite loop leads to the tab being killed.

### Expected behavior

SWC doesn't run into an infinite loop. It should error instead if the syntax is deemed invalid.

### Actual behavior

SWC consumes 100% CPU and is stuck in an infinite loop.

### Version

@swc/cli: 0.1.62 @swc/core: 1.3.44

### Additional context

Related https://github.com/denoland/deno/issues/18565 

Pull request:
fix(es/parser): fix infinite loop on jsx in js
<!-- Note: CI script will automatically rebase your PR so please do not rebase unless required -->

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

This fixes an infinite loop in the parser when it encountered an invalid token. This was easiest to reproduce by trying to parse JSX as JS.

I'm new to the swc codebase and I couldn't find places which a have a similar logic. So I opted to break out of the loop instead of modifying the `bump!` macro. Let me know if that is not the proper way to do it. 

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

**BREAKING CHANGE:**
no
<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

**Related issue (if exists):**

Fixes #7189


Patch:
diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs
index d6a9b82692..cc8160ad3d 100644
--- a/crates/swc_ecma_parser/src/parser/stmt.rs
+++ b/crates/swc_ecma_parser/src/parser/stmt.rs
@@ -845,6 +845,10 @@ impl<'a, I: Tokens> Parser<I> {
 
             while !eat!(self, ';') {
                 bump!(self);
+
+                if let Some(Token::Error(_)) = self.input.cur() {
+                    break;
+                }
             }
         }
 


Test patch:
diff --git a/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js b/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js
new file mode 100644
index 0000000000..00d7e01ada
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js
@@ -0,0 +1,5 @@
+const a = (
+  <section>
+    <a href="/foo">foo</a>
+  </section>
+);
diff --git a/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js.swc-stderr
new file mode 100644
index 0000000000..d7d08fa07e
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/errors/jsx_in_js/input.js.swc-stderr
@@ -0,0 +1,32 @@
+
+  x Unterminated regexp literal
+   ,-[$DIR/tests/errors/jsx_in_js/input.js:2:1]
+ 2 |   <section>
+ 3 |     <a href="/foo">foo</a>
+   :                        ^^^
+ 4 |   </section>
+   `----
+
+  x Expression expected
+   ,-[$DIR/tests/errors/jsx_in_js/input.js:1:1]
+ 1 | const a = (
+ 2 |   <section>
+   :   ^
+ 3 |     <a href="/foo">foo</a>
+   `----
+
+  x Expression expected
+   ,-[$DIR/tests/errors/jsx_in_js/input.js:2:1]
+ 2 |   <section>
+ 3 |     <a href="/foo">foo</a>
+   :     ^
+ 4 |   </section>
+   `----
+
+  x Expected a semicolon
+   ,-[$DIR/tests/errors/jsx_in_js/input.js:2:1]
+ 2 |   <section>
+ 3 |     <a href="/foo">foo</a>
+   :        ^^^^
+ 4 |   </section>
+   `----