Repository: swc-project/swc (rust)

Issue:
[Bug]: Unable to use `await` as an identifier in `ExprStmt`
### Describe the bug

SWC fails to transpile `input.js`, which uses `await` as an identifier.

### Input code

```typescript
// input.js
try { await; } catch { console.log("caught"); }
```


### Config

_No response_

### Playground link

https://play.swc.rs/?version=1.3.11&code=H4sIAAAAAAAAA9PXV8jMKygt0csq5iopqlSoVkgsT8wssVaoVUhOLEnOAAok5%2BcV5%2Bek6uXkp2soJSeWpmeUKGkCFQAAP70bcTsAAAA%3D&config=H4sIAAAAAAAAA0WMTQrEIAxG75K1286id5hDBCctFv9IUhgR714tlu7C915ehUMsrBUyshCPS0pU%2FMMKZAOKZZcVTNf6tKEXagYUeScdiiyd%2BZSEJjUQXHRbGSWbQmYSeRHG3T9m66GQfucYKmjJdAc%2F0N7G%2FHPynaLySe0Cj9ke9LUAAAA%3D

### Expected behavior

`input.js` is a valid JavaScript program:
```console
$ d8 input.js
caught
```
so it should be transpiled by SWC.

### Actual behavior

SWC crashes when the `input.js` is given:
<img width="474" alt="image" src="https://user-images.githubusercontent.com/68288688/199188970-db930701-c272-4ccf-9438-db07c8df5958.png">


### Version

1.3.11 (default SWC playground)

### Additional context

_No response_

Pull request:
fix(ecma/parser): fix parsing await as ident
<!-- 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:**

Fix bug in parser with `await` ident

**BREAKING CHANGE:**

No

**Related issue (if exists):**

Fixes #6301

Patch:
diff --git a/crates/swc_ecma_parser/src/parser/expr/ops.rs b/crates/swc_ecma_parser/src/parser/expr/ops.rs
index 018aa2e7d8..410c4dd063 100644
--- a/crates/swc_ecma_parser/src/parser/expr/ops.rs
+++ b/crates/swc_ecma_parser/src/parser/expr/ops.rs
@@ -331,10 +331,6 @@ impl<I: Tokens> Parser<I> {
         }
 
         if is!(self, "await") {
-            let ctx = self.ctx();
-            if ctx.in_function && !ctx.in_async {
-                self.emit_err(self.input.cur_span(), SyntaxError::AwaitInFunction);
-            }
             return self.parse_await_expr();
         }
 
@@ -379,14 +375,18 @@ impl<I: Tokens> Parser<I> {
 
         let span = span!(self, start);
 
-        if is_one_of!(self, ')', ']') && !self.ctx().in_async {
-            if ctx.in_async || ctx.module {
+        if is_one_of!(self, ')', ']', ';', ',') && !ctx.in_async {
+            if ctx.module {
                 self.emit_err(span, SyntaxError::InvalidIdentInAsync);
             }
 
             return Ok(Box::new(Expr::Ident(Ident::new(js_word!("await"), span))));
         }
 
+        if ctx.in_function && !ctx.in_async {
+            self.emit_err(self.input.cur_span(), SyntaxError::AwaitInFunction);
+        }
+
         if ctx.in_parameters && !ctx.in_function {
             self.emit_err(span, SyntaxError::AwaitParamInAsync);
         }
diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs
index a35930b913..3ad1bfbf28 100644
--- a/crates/swc_ecma_parser/src/parser/stmt.rs
+++ b/crates/swc_ecma_parser/src/parser/stmt.rs
@@ -2485,4 +2485,46 @@ const foo;"#;
 
         test_parser(src, Default::default(), |p| p.parse_script());
     }
+
+    #[test]
+    fn issue_6301_await_expr_stmt() {
+        let src = "try { await; } catch { console.log('caught'); }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
+
+    #[test]
+    fn issue_6301_await_expr_stmt_1() {
+        let src = "try { await, await; } catch { console.log('caught'); }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
+
+    #[test]
+    fn issue_6301_await_expr_stmt_2() {
+        let src = "function test() { await; }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
+
+    #[test]
+    fn issue_6301_await_expr_stmt_3() {
+        let src = "function test() { await, await; }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
+
+    #[test]
+    fn issue_6301_await_expr_stmt_4() {
+        let src = "function test() { [await]; }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
+
+    #[test]
+    fn issue_6301_await_expr_stmt_5() {
+        let src = "function test() { (await); }";
+
+        test_parser(src, Default::default(), |p| p.parse_script());
+    }
 }


Test patch:
diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/1aefe47e20eb91fa.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/1aefe47e20eb91fa.module.js.stderr
index bd224bc476..2762a3a2f8 100644
--- a/crates/swc_ecma_parser/tests/test262-error-references/fail/1aefe47e20eb91fa.module.js.stderr
+++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/1aefe47e20eb91fa.module.js.stderr
@@ -1,12 +1,11 @@
 
-  x Unexpected token `<eof>`. Expected this, import, async, function, [ for array literal, { for object literal, @ for decorator, function, class, null, true, false, number, bigint, string, regexp,
-  | ` for template literal, (, or an identifier
+  x top level await requires target to es2017 or higher and topLevelAwait:true for ecmascript
    ,-[$DIR/tests/test262-parser/fail/1aefe47e20eb91fa.module.js:1:1]
  1 | await
    : ^^^^^
    `----
 
-  x top level await requires target to es2017 or higher and topLevelAwait:true for ecmascript
+  x `await` cannot be used as an identifier in an async context
    ,-[$DIR/tests/test262-parser/fail/1aefe47e20eb91fa.module.js:1:1]
  1 | await
    : ^^^^^