Repository: babel/babel (TypeScript)

Issue:
[Bug]: `using` in `switch` is not compiled
### 💻

- [ ] Would you like to work on a fix?

### How are you using Babel?

Other (Next.js, Gatsby, vue-cli, ...)

### Input code

```js
{
  switch (1) {
    case 1:
      using a = 1;
    case 2:
      using b = 2;
  }
  using c = 4;
}
```

https://babeljs.io/repl#?browsers=&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=N4KABGDODuCWAuBjAFmAFARgJRlBCiAhpAKZgYBc4-EArpLAHYDmYhYAvOQNzUHFkATFRp0GLMACNOYQbwgBfavSatEMgCy8FQA&debug=false&forceAllTransforms=false&modules=commonjs&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=stage-3%2Ctypescript&prettier=false&targets=&version=7.24.4&externalPlugins=&assumptions=%7B%7D

### Configuration file name

_No response_

### Configuration

_No response_

### Current and expected behavior

`using` is not transpiled, but it shuold

### Environment

v7.24.4

### Possible solution

_No response_

### Additional context

_No response_


Hints:

Patch:
diff --git a/packages/babel-helper-transform-fixture-test-runner/src/index.ts b/packages/babel-helper-transform-fixture-test-runner/src/index.ts
--- a/packages/babel-helper-transform-fixture-test-runner/src/index.ts
+++ b/packages/babel-helper-transform-fixture-test-runner/src/index.ts
@@ -428,6 +428,8 @@ async function run(task: Test) {
     } catch (e) {
       if (!process.env.OVERWRITE && task.sourceMap) throw e;
 
+      task.sourceMapFile.loc ??= task.taskDir + "/source-map.json";
+
       console.log(`Updated test file: ${task.sourceMapFile.loc}`);
       fs.writeFileSync(
         task.sourceMapFile.loc,
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/src/index.ts b/packages/babel-plugin-proposal-explicit-resource-management/src/index.ts
--- a/packages/babel-plugin-proposal-explicit-resource-management/src/index.ts
+++ b/packages/babel-plugin-proposal-explicit-resource-management/src/index.ts
@@ -160,6 +160,69 @@ export default declare(api => {
         }
       }
     },
+    SwitchStatement(path, state) {
+      let ctx: t.Identifier | null = null;
+      let needsAwait = false;
+
+      const { cases } = path.node;
+      for (const c of cases) {
+        for (const stmt of c.consequent) {
+          if (isUsingDeclaration(stmt)) {
+            if (
+              !process.env.BABEL_8_BREAKING &&
+              !state.availableHelper("usingCtx")
+            ) {
+              path.traverse({
+                VariableDeclaration(path) {
+                  const { node } = path;
+                  if (!isUsingDeclaration(node)) return;
+                  throw path.buildCodeFrameError(
+                    "`using` declarations inside `switch` statements are not supported by your current `@babel/core` version, please update to a more recent one",
+                  );
+                },
+              });
+            }
+
+            ctx ??= path.scope.generateUidIdentifier("usingCtx");
+
+            const isAwaitUsing = stmt.kind === "await using";
+            needsAwait ||= isAwaitUsing;
+
+            stmt.kind = "const";
+            for (const decl of stmt.declarations) {
+              decl.init = t.callExpression(
+                t.memberExpression(
+                  t.cloneNode(ctx),
+                  isAwaitUsing ? t.identifier("a") : t.identifier("u"),
+                ),
+                [decl.init],
+              );
+            }
+          }
+        }
+      }
+      if (!ctx) return;
+
+      const disposeCall = t.callExpression(
+        t.memberExpression(t.cloneNode(ctx), t.identifier("d")),
+        [],
+      );
+
+      const replacement = template.statement.ast`
+        try {
+          var ${t.cloneNode(ctx)} = ${state.addHelper("usingCtx")}();
+          ${path.node}
+        } catch (_) {
+          ${t.cloneNode(ctx)}.e = _;
+        } finally {
+          ${needsAwait ? t.awaitExpression(disposeCall) : disposeCall}
+        }
+      ` as t.TryStatement;
+
+      t.inherits(replacement, path.node);
+
+      path.replaceWith(replacement);
+    },
   };
 
   const transformUsingDeclarationsVisitorSkipFn: Visitor<PluginPass> =


Test patch:
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/input.js b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/input.js
@@ -0,0 +1,10 @@
+function f() {
+  switch (v) {
+    case 0:
+      using x = 0;
+      break;
+    default:
+      using y = 1;
+      break;
+  };
+}
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/output.js b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/output.js
@@ -0,0 +1,18 @@
+function f() {
+  try {
+    var _usingCtx = babelHelpers.usingCtx();
+    switch (v) {
+      case 0:
+        const x = _usingCtx.u(0);
+        break;
+      default:
+        const y = _usingCtx.u(1);
+        break;
+    }
+  } catch (_) {
+    _usingCtx.e = _;
+  } finally {
+    _usingCtx.d();
+  }
+  ;
+}
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map-visual.txt b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map-visual.txt
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map-visual.txt
@@ -0,0 +1,173 @@
+  (1:0-9) function f()            <--    (1:0-9) function f() 
+          ^^^^^^^^^                              ^^^^^^^^^
+
+ (1:9-10) ion f() {               <--   (1:9-10) ion f() {
+              ^                                      ^
+
+(1:10-13) on f() {                <--  (1:10-11) on f() {
+              ^^^                                    ^
+
+(1:10-13) on f() {                <--  (1:11-13) n f() {
+              ^^^                                    ^^
+
+(1:13-14) f() {                   <--  (1:13-14) f() {
+              ^                                      ^
+
+ (2:2-10)   switch (v) {          <--    (2:2-7)   try {
+            ^^^^^^^^                               ^^^^^
+
+ (2:2-10)   switch (v) {          <--    (3:4-8)     var _usi
+            ^^^^^^^^                                 ^^^^
+
+ (2:2-10)   switch (v) {          <--   (3:8-17) var _usingCtx = b
+            ^^^^^^^^                                 ^^^^^^^^^
+
+ (2:2-10)   switch (v) {          <--  (3:17-20) gCtx = babe
+            ^^^^^^^^                                 ^^^
+
+ (2:2-10)   switch (v) {          <--  (3:20-32) x = babelHelpers.usi
+            ^^^^^^^^                                 ^^^^^^^^^^^^
+
+ (2:2-10)   switch (v) {          <--  (3:32-33) pers.usin
+            ^^^^^^^^                                 ^
+
+ (2:2-10)   switch (v) {          <--  (3:33-41) ers.usingCtx();
+            ^^^^^^^^                                 ^^^^^^^^
+
+ (2:2-10)   switch (v) {          <--  (3:41-44) gCtx();
+            ^^^^^^^^                                 ^^^
+
+ (2:2-10)   switch (v) {          <--   (4:4-12)     switch (v) {
+            ^^^^^^^^                                 ^^^^^^^^
+
+(2:10-11) ch (v) {                <--  (4:12-13) ch (v) {
+              ^                                      ^
+
+(2:11-14) h (v) {                 <--  (4:13-16) h (v) {
+              ^^^                                    ^^^
+
+  (3:4-9)     case 0:             <--   (5:6-11)     case 0:
+              ^^^^^                                  ^^^^^
+
+ (3:9-10) ase 0:                  <--  (5:11-12) ase 0:
+              ^                                      ^
+
+(3:10-11) se 0:                   <--  (5:12-13) se 0:
+              ^                                      ^
+
+ (4:6-12)     using x =           <--   (6:8-14)     const x = 
+              ^^^^^^                                 ^^^^^^
+
+(4:12-13) ing x = 0               <--  (6:14-15) nst x = _
+              ^                                      ^
+
+(4:13-16) ng x = 0;               <--  (6:15-18) st x = _usi
+              ^^^                                    ^^^
+
+(4:13-16) ng x = 0;               <--  (6:18-27) x = _usingCtx.u(0
+              ^^^                                    ^^^^^^^^^
+
+(4:13-16) ng x = 0;               <--  (6:27-28) gCtx.u(0)
+              ^^^                                    ^
+
+(4:13-16) ng x = 0;               <--  (6:28-29) Ctx.u(0);
+              ^^^                                    ^
+
+(4:13-16) ng x = 0;               <--  (6:29-30) tx.u(0);
+              ^^^                                    ^
+
+(4:16-17) x = 0;                  <--  (6:30-31) x.u(0);
+              ^                                      ^
+
+(4:17-18)  = 0;                   <--  (6:31-33) .u(0);
+              ^                                      ^^
+
+ (5:6-12)     break;              <--   (7:8-14)     break;
+              ^^^^^^                                 ^^^^^^
+
+ (6:4-12)     default:            <--   (8:6-14)     default:
+              ^^^^^^^^                               ^^^^^^^^
+
+ (7:6-12)     using y =           <--   (9:8-14)     const y = 
+              ^^^^^^                                 ^^^^^^
+
+(7:12-13) ing y = 1               <--  (9:14-15) nst y = _
+              ^                                      ^
+
+(7:13-16) ng y = 1;               <--  (9:15-18) st y = _usi
+              ^^^                                    ^^^
+
+(7:13-16) ng y = 1;               <--  (9:18-27) y = _usingCtx.u(1
+              ^^^                                    ^^^^^^^^^
+
+(7:13-16) ng y = 1;               <--  (9:27-28) gCtx.u(1)
+              ^^^                                    ^
+
+(7:13-16) ng y = 1;               <--  (9:28-29) Ctx.u(1);
+              ^^^                                    ^
+
+(7:13-16) ng y = 1;               <--  (9:29-30) tx.u(1);
+              ^^^                                    ^
+
+(7:16-17) y = 1;                  <--  (9:30-31) x.u(1);
+              ^                                      ^
+
+(7:17-18)  = 1;                   <--  (9:31-33) .u(1);
+              ^                                      ^^
+
+ (8:6-12)     break;              <--  (10:8-14)     break;
+              ^^^^^^                                 ^^^^^^
+
+  (9:2-3)   };                    <--   (11:4-5)     }
+            ^                                        ^
+
+  (9:3-4)   };                    <--  (12:2-11)   } catch (_) {
+             ^                                     ^^^^^^^^^
+
+  (9:3-4)   };                    <--  (12:11-12) ch (_) {
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (12:12-15) h (_) {
+             ^                                        ^^^
+
+  (9:3-4)   };                    <--  (13:4-13)     _usingCtx.e =
+             ^                                       ^^^^^^^^^
+
+  (9:3-4)   };                    <--  (13:13-14) gCtx.e = 
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (13:14-15) Ctx.e = _
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (13:15-18) tx.e = _;
+             ^                                        ^^^
+
+  (9:3-4)   };                    <--  (13:18-19) e = _;
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (13:19-20)  = _;
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (14:2-13)   } finally {
+             ^                                     ^^^^^^^^^^^
+
+  (9:3-4)   };                    <--  (15:4-13)     _usingCtx.d()
+             ^                                       ^^^^^^^^^
+
+  (9:3-4)   };                    <--  (15:13-14) gCtx.d();
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (15:14-15) Ctx.d();
+             ^                                        ^
+
+  (9:3-4)   };                    <--  (15:15-18) tx.d();
+             ^                                        ^^^
+
+  (9:3-4)   };                    <--   (16:2-3)   }
+             ^                                     ^
+
+  (9:3-4)   };                    <--   (17:2-3)   ;
+             ^                                     ^
+
+ (10:0-1) }                       <--   (18:0-1) }
+          ^                                      ^
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map.json b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map.json
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/source-maps/switch/source-map.json
@@ -0,0 +1,24 @@
+{
+  "version": 3,
+  "names": [
+    "f",
+    "_usingCtx",
+    "babelHelpers",
+    "usingCtx",
+    "v",
+    "x",
+    "u",
+    "y",
+    "_",
+    "e",
+    "d"
+  ],
+  "sources": [
+    "source-maps/switch/input.js"
+  ],
+  "sourcesContent": [
+    "function f() {\n  switch (v) {\n    case 0:\n      using x = 0;\n      break;\n    default:\n      using y = 1;\n      break;\n  };\n}"
+  ],
+  "mappings": "AAAA,SAASA,CAACA,CAAA,EAAG;EACX;IAAA,IAAAC,SAAA,GAAAC,YAAA,CAAAC,QAAA;IAAA,QAAQC,CAAC;MACP,KAAK,CAAC;QACJ,MAAMC,CAAC,GAAAJ,SAAA,CAAAK,CAAA,CAAG,CAAC;QACX;MACF;QACE,MAAMC,CAAC,GAAAN,SAAA,CAAAK,CAAA,CAAG,CAAC;QACX;IACJ;EAAC,SAAAE,CAAA;IAAAP,SAAA,CAAAQ,CAAA,GAAAD,CAAA;EAAA;IAAAP,SAAA,CAAAS,CAAA;EAAA;EAAA;AACH",
+  "ignoreList": []
+}
\ No newline at end of file
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/input.js b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/input.js
@@ -0,0 +1,10 @@
+async function f() {
+  switch (v) {
+    case 0:
+      await using x = 0;
+      break;
+    default:
+      await using y = 1;
+      break;
+  }
+}
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/output.mjs b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/output.mjs
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-await/switch/output.mjs
@@ -0,0 +1,17 @@
+async function f() {
+  try {
+    var _usingCtx = babelHelpers.usingCtx();
+    switch (v) {
+      case 0:
+        const x = _usingCtx.a(0);
+        break;
+      default:
+        const y = _usingCtx.a(1);
+        break;
+    }
+  } catch (_) {
+    _usingCtx.e = _;
+  } finally {
+    await _usingCtx.d();
+  }
+}
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/input.js b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/input.js
@@ -0,0 +1,10 @@
+function f() {
+  switch (v) {
+    case 0:
+      using x = 0;
+      break;
+    default:
+      using y = 1;
+      break;
+  };
+}
diff --git a/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/output.js b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-explicit-resource-management/test/fixtures/transform-sync/switch/output.js
@@ -0,0 +1,18 @@
+function f() {
+  try {
+    var _usingCtx = babelHelpers.usingCtx();
+    switch (v) {
+      case 0:
+        const x = _usingCtx.u(0);
+        break;
+      default:
+        const y = _usingCtx.u(1);
+        break;
+    }
+  } catch (_) {
+    _usingCtx.e = _;
+  } finally {
+    _usingCtx.d();
+  }
+  ;
+}