Repository: swc-project/swc (rust)

Issue:
es5 will generate illegal js code
### Describe the bug

swc generates illegal js code when i use input code

### Input code

```typescript
async function a(fn) {
    (await fn()).a = "123";
}
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "commonjs"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.3.76&code=H4sIAAAAAAAAA0ssrsxLVkgrzUsuyczPU0jUSMvTVKjmUgACjcTyxMwShbQ8DU1NvUQFWwVDa65aANML9EIwAAAA&config=H4sIAAAAAAAAA1WPSw7DIAxE95wCed1tN71DD2FRJwLxEyZSUZS7Fyikzc4z8%2ByRdyElGFbwkHsdq4iYmNKpq8PFZ3xXB0g5ZJV0zHCbqeEWLWiZunV8E8iYVsp9i%2B8DBxsC08SH57TXS%2FkvVMHFRMxXsKHoV0vXOjEqwYXX1sPxSC6xqXbNBW8YfuRsPK%2BD5udcz2kjcXwAmJf30BkBAAA%3D

### Expected behavior

correctly transpile `await` in left hand side of assignment expressions

### Actual behavior

``` javascript
function a(fn) {
    return _a.apply(this, arguments);
}
function _a() {
    _a = _async_to_generator(function(fn) {
        return _ts_generator(this, function(_state) {
            (yield fn()).a = 1; // cannot use yield in ordinary functions
            return [
                2
            ];
        });
    });
    return _a.apply(this, arguments);
}
```

### Version

1.3.76

### Additional context

_No response_

Pull request:
fix(es/compat): Visit assign expr in generator
**Related issue:**
 - Closes #7809 

Patch:
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/generator.rs b/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
index a6da0916a0..a409203a50 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
@@ -572,72 +572,70 @@ impl VisitMut for Generator {
                 e.visit_mut_children_with(self);
             }
 
-            Expr::Assign(node) => {
-                if contains_yield(&node.right) {
-                    match node.left.as_expr_mut() {
-                        Some(Expr::Member(left)) => {
-                            match &mut left.prop {
-                                MemberProp::Ident(..) | MemberProp::PrivateName(..) => {
-                                    //      a.b = yield;
-                                    //
-                                    // [intermediate]
-                                    //  .local _a
-                                    //      _a = a;
-                                    //  .yield resumeLabel
-                                    //  .mark resumeLabel
-                                    //      _a.b = %sent%;
-
-                                    left.obj.visit_mut_with(self);
-                                    let obj = self.cache_expression(left.obj.take());
-
-                                    left.obj = Box::new(Expr::Ident(obj));
-                                }
-                                MemberProp::Computed(prop) => {
-                                    // [source]
-                                    //      a[b] = yield;
-                                    //
-                                    // [intermediate]
-                                    //  .local _a, _b
-                                    //      _a = a;
-                                    //      _b = b;
-                                    //  .yield resumeLabel
-                                    //  .mark resumeLabel
-                                    //      _a[_b] = %sent%;
-                                    let prop_span = prop.span;
-
-                                    left.obj.visit_mut_with(self);
-                                    let obj = self.cache_expression(left.obj.take());
-
-                                    prop.visit_mut_with(self);
-                                    let prop = self.cache_expression(prop.expr.take());
-
-                                    left.obj = Box::new(Expr::Ident(obj));
-                                    left.prop = MemberProp::Computed(ComputedPropName {
-                                        span: prop_span,
-                                        expr: Box::new(Expr::Ident(prop)),
-                                    });
-                                }
+            Expr::Assign(node) if contains_yield(&node.right) => {
+                match node.left.as_expr_mut() {
+                    Some(Expr::Member(left)) => {
+                        match &mut left.prop {
+                            MemberProp::Ident(..) | MemberProp::PrivateName(..) => {
+                                //      a.b = yield;
+                                //
+                                // [intermediate]
+                                //  .local _a
+                                //      _a = a;
+                                //  .yield resumeLabel
+                                //  .mark resumeLabel
+                                //      _a.b = %sent%;
+
+                                left.obj.visit_mut_with(self);
+                                let obj = self.cache_expression(left.obj.take());
+
+                                left.obj = Box::new(Expr::Ident(obj));
+                            }
+                            MemberProp::Computed(prop) => {
+                                // [source]
+                                //      a[b] = yield;
+                                //
+                                // [intermediate]
+                                //  .local _a, _b
+                                //      _a = a;
+                                //      _b = b;
+                                //  .yield resumeLabel
+                                //  .mark resumeLabel
+                                //      _a[_b] = %sent%;
+                                let prop_span = prop.span;
+
+                                left.obj.visit_mut_with(self);
+                                let obj = self.cache_expression(left.obj.take());
+
+                                prop.visit_mut_with(self);
+                                let prop = self.cache_expression(prop.expr.take());
+
+                                left.obj = Box::new(Expr::Ident(obj));
+                                left.prop = MemberProp::Computed(ComputedPropName {
+                                    span: prop_span,
+                                    expr: Box::new(Expr::Ident(prop)),
+                                });
                             }
-                            // [source]
-                        }
-                        _ => {
-                            node.left.visit_mut_with(self);
                         }
+                        // [source]
+                    }
+                    _ => {
+                        node.left.visit_mut_with(self);
                     }
-                    if node.op != op!("=") {
-                        let left_of_right = self.cache_expression(node.left.take().expect_expr());
+                }
+                if node.op != op!("=") {
+                    let left_of_right = self.cache_expression(node.left.take().expect_expr());
 
-                        node.right.visit_mut_with(self);
+                    node.right.visit_mut_with(self);
 
-                        *e = Expr::Assign(AssignExpr {
-                            span: node.right.span(),
-                            op: node.op,
-                            left: left_of_right.into(),
-                            right: node.right.take(),
-                        });
-                    } else {
-                        node.right.visit_mut_with(self);
-                    }
+                    *e = Expr::Assign(AssignExpr {
+                        span: node.right.span(),
+                        op: node.op,
+                        left: left_of_right.into(),
+                        right: node.right.take(),
+                    });
+                } else {
+                    node.right.visit_mut_with(self);
                 }
             }
 


Test patch:
diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs b/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs
index 1b7a8f5499..4a29cfb36d 100644
--- a/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs
+++ b/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs
@@ -1937,3 +1937,47 @@ test_exec!(
     await res;
     "
 );
+
+test!(
+    Syntax::default(),
+    |_| {
+        let mark = Mark::fresh(Mark::root());
+        es2015::<SingleThreadedComments>(mark, None, Default::default())
+    },
+    issue_7809,
+    r#"
+    function a(fn) {
+        return _a.apply(this, arguments);
+    }
+    function _a() {
+        _a = _async_to_generator(function*(fn) {
+            (yield fn()).a = 1;
+        });
+        return _a.apply(this, arguments);
+    }    
+    "#,
+    r#"
+    function a(fn) {
+        return _a.apply(this, arguments);
+    }
+    function _a() {
+        _a = _async_to_generator(function(fn) {
+            return _ts_generator(this, function(_state) {
+                switch(_state.label){
+                    case 0:
+                        return [
+                            4,
+                            fn()
+                        ];
+                    case 1:
+                        _state.sent().a = 1;
+                        return [
+                            2
+                        ];
+                }
+            });
+        });
+        return _a.apply(this, arguments);
+    }           
+    "#
+);