Repository: swc-project/swc (rust)

Issue:
Wrong transpilation: return inside while from ES5-transpiled generator/async functions
### Describe the bug

`return obj;` inside a while in ES5-transpiled generators are not being transpiled to `return [2, obj];`, potentially causing infinite loops. As `async` functions are transpiled using generators, this also affects async functions.

(Thank you oka@chromium.org for finding this bug: https://crrev.com/c/4659623)

### Input code

```typescript
async function asyncWhile() {
    while (true) {
        return {};
    }
}

function* generatorWhile() {
    while (true) {
        return {};
    }
}
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.3.66&code=H4sIAAAAAAAAA0ssrsxLVkgrzUsuyczPU0gEccMzMnNSNTQVqrkUgKAcxFPQKCkqTYUJgUBRaklpUZ5Cda01WKiWq5aLC2aMlkJ6al5qUWJJfhG5ZgEALxL9bJgAAAA%3D&config=H4sIAAAAAAAAA1WPSw7DIAwF9zkF8rrbdtE79BCIOhERP9mOVBTl7oUE0maH3xszsA5KwcwGnmotxzIkTYx0ziXhHER%2FSgKSE7IhmwRuvRWu1agd4x5tRwOiaUKpW8j3hoOLkbHjLfM22DH%2FC030iZD5ClZUh8nhVTc0Jfj4XvayfaQ%2B9tA%2F4Ad12XkxWH71TaEFh%2B0LYuVI0xQBAAA%3D

### Expected behavior

Both functions in the example immediately return an empty object after calling `.next()` / awaiting.

### Actual behavior

Both functions in the example run infinitely.

### Version

1.3.66

### Additional context

_No response_

Pull request:
fix(es/compat): Visit children of `while` statement in the `generator` pass
**Description:**


**Related issue:**

 - Closes #7622.

Patch:
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/generator.rs b/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
index fa64fdc772..a6da0916a0 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/generator.rs
@@ -1646,6 +1646,8 @@ impl Generator {
             self.emit_break(loop_label, None);
             self.end_loop_block();
         } else {
+            node.visit_mut_children_with(self);
+
             self.emit_stmt(Stmt::While(node));
         }
     }


Test patch:
diff --git a/crates/swc/tests/fixture/issues-7xxx/7622/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7622/input/.swcrc
new file mode 100644
index 0000000000..887e89d7af
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7622/input/.swcrc
@@ -0,0 +1,19 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "typescript",
+            "tsx": false
+        },
+        "target": "es5",
+        "loose": false,
+        "minify": {
+            "compress": false,
+            "mangle": false
+        }
+    },
+    "module": {
+        "type": "es6"
+    },
+    "minify": false,
+    "isModule": true
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-7xxx/7622/input/1.js b/crates/swc/tests/fixture/issues-7xxx/7622/input/1.js
new file mode 100644
index 0000000000..64a31c9892
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7622/input/1.js
@@ -0,0 +1,11 @@
+async function asyncWhile() {
+    while (true) {
+        return {};
+    }
+}
+
+function* generatorWhile() {
+    while (true) {
+        return {};
+    }
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-7xxx/7622/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7622/output/1.js
new file mode 100644
index 0000000000..a569744313
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7622/output/1.js
@@ -0,0 +1,34 @@
+import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
+import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
+function asyncWhile() {
+    return _asyncWhile.apply(this, arguments);
+}
+function _asyncWhile() {
+    _asyncWhile = _async_to_generator(function() {
+        return _ts_generator(this, function(_state) {
+            while(true){
+                return [
+                    2,
+                    {}
+                ];
+            }
+            return [
+                2
+            ];
+        });
+    });
+    return _asyncWhile.apply(this, arguments);
+}
+function generatorWhile() {
+    return _ts_generator(this, function(_state) {
+        while(true){
+            return [
+                2,
+                {}
+            ];
+        }
+        return [
+            2
+        ];
+    });
+}