Repository: swc-project/swc (rust)

Issue:
TypeError: _loop is not a function
### Describe the bug

See playground link. The output code line 5 is:

```while(stack.shift() !== undefined)_loop();```

Which throws an Unhandled Runtime Error: TypeError: _loop is not a function because _loop has not been defined yet.

### Input code

```typescript
export const loopError = () => {
  const stack: number[] = [1];
  while (stack.shift() !== undefined) {
    const object = 1;
    [].map((): number => object);
  }
  const kind = 0;
  switch (kind) {
    case 0:
      break;
  }
};
```


### Config

```json
Using the default swc config with nextjs
```


### Playground link

https://play.swc.rs/?version=1.3.74&code=H4sIAAAAAAAAAz2OTQ6DIBCF955iuoON0a2E7noK4wJhjFQFAxibNN69gNXd5P188%2FCzWhdAWuMDzNauL%2BesAw6EAn%2FCt4C%2F54OQUwNmW3p0bRcTbd2xaO%2BjnhFI9ks%2F6iHE6oNz2IzCQRtUNGMukO3fKEPs1yyrbVcuYiWEXvD09wzRlDjuCZM2KvaqpPpdBzkCSdrNFx6havIN0DsU0wk4WPED5UaMfugAAAA%3D&config=H4sIAAAAAAAAA1WPSw7DIAwF9zkF8rrbdtE79BCIOhERP9mOVBTl7oUE0maH3xszsA5KwcwGnmotxzIkTYx0ziXhHER%2FSgKSE7IhmwRuvRWu1agd4x5tRwOiaUKpW8j3hoOLkbHjLfM22DH%2FC030iZD5ClZUh8nhVTc0Jfj4XvayfaQ%2B9tA%2F4Ad12XkxWH71TaEFh%2B0LYuVI0xQBAAA%3D

### SWC Info output

_No response_

### Expected behavior

No runtime error

### Actual behavior

_No response_

### Version

1.3.80

### Additional context

_No response_

Pull request description:
fix(es/compat): Make `SwitchCase` handler of `block-scoping` stateless
**Description:**


**Related issue:**

 - Closes #7885

Patch:
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/block_scoping/mod.rs b/crates/swc_ecma_transforms_compat/src/es2015/block_scoping/mod.rs
index 4c80ceefd3..ce18711f7e 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/block_scoping/mod.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/block_scoping/mod.rs
@@ -431,13 +431,6 @@ impl VisitMut for BlockScoping {
         self.handle_capture_of_vars(&mut node.body);
     }
 
-    fn visit_mut_while_stmt(&mut self, node: &mut WhileStmt) {
-        self.visit_mut_with_scope(ScopeKind::new_loop(), &mut node.body);
-
-        node.test.visit_mut_with(self);
-        self.handle_capture_of_vars(&mut node.body);
-    }
-
     fn visit_mut_for_in_stmt(&mut self, node: &mut ForInStmt) {
         let blockifyed = self.blockify_for_stmt_body(&mut node.body);
         let lexical_var = if let ForHead::VarDecl(decl) = &node.left {
@@ -544,6 +537,14 @@ impl VisitMut for BlockScoping {
         self.visit_mut_stmt_like(n);
     }
 
+    fn visit_mut_switch_case(&mut self, n: &mut SwitchCase) {
+        let old_vars = self.vars.take();
+
+        n.visit_mut_children_with(self);
+
+        self.vars = old_vars;
+    }
+
     fn visit_mut_var_decl(&mut self, var: &mut VarDecl) {
         let old = self.var_decl_kind;
         self.var_decl_kind = var.kind;
@@ -569,6 +570,13 @@ impl VisitMut for BlockScoping {
             }
         }
     }
+
+    fn visit_mut_while_stmt(&mut self, node: &mut WhileStmt) {
+        self.visit_mut_with_scope(ScopeKind::new_loop(), &mut node.body);
+
+        node.test.visit_mut_with(self);
+        self.handle_capture_of_vars(&mut node.body);
+    }
 }
 
 impl BlockScoping {
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/for_of.rs b/crates/swc_ecma_transforms_compat/src/es2015/for_of.rs
index b509443934..d7ddb6be38 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/for_of.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/for_of.rs
@@ -670,7 +670,7 @@ impl VisitMut for ForOf {
                         *s = self.fold_for_stmt(Some(label.clone()), stmt.take());
                     }
                     _ => {
-                        body.visit_mut_children_with(self);
+                        body.visit_mut_with(self);
                     }
                 }
             }


Test patch:
diff --git a/crates/swc/tests/fixture/issues-7xxx/7885/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7885/input/.swcrc
new file mode 100644
index 0000000000..887e89d7af
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7885/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/7885/input/1.js b/crates/swc/tests/fixture/issues-7xxx/7885/input/1.js
new file mode 100644
index 0000000000..d4574a17ba
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7885/input/1.js
@@ -0,0 +1,12 @@
+export const loopError = () => {
+    const stack: number[] = [1];
+    while (stack.shift() !== undefined) {
+        const object = 1;
+        [].map((): number => object);
+    }
+    const kind = 0;
+    switch (kind) {
+        case 0:
+            break;
+    }
+};
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-7xxx/7885/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7885/output/1.js
new file mode 100644
index 0000000000..5f67318085
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7885/output/1.js
@@ -0,0 +1,17 @@
+export var loopError = function() {
+    var _loop = function() {
+        var object = 1;
+        [].map(function() {
+            return object;
+        });
+    };
+    var stack = [
+        1
+    ];
+    while(stack.shift() !== undefined)_loop();
+    var kind = 0;
+    switch(kind){
+        case 0:
+            break;
+    }
+};