Repository: babel/babel (TypeScript)

Issue:
[Bug]: Babel throws when a decorated class expression contains a static block
### 💻

- [X] Would you like to work on a fix?

### How are you using Babel?

Programmatic API (`babel.transform`, `babel.parse`)

### Input code

```js
const dec = () => {};
0, @dec class { static {} }
```

[REPL](https://babel.dev/repl#?browsers=defaults&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=MYewdgzgLgBAJgU2DAvDAFASlQPhgbwF8BuAKAAYAaGAAUWWABsBDCCAmaZqAS2SJiEgA&debug=false&forceAllTransforms=false&shippedProposals=true&circleciRepo=&evaluate=true&fileSize=false&timeTravel=false&sourceType=module&lineWrap=false&presets=stage-2&prettier=false&targets=&version=7.20.1&externalPlugins=&assumptions=%7B%7D)

### Configuration file name

_No response_

### Configuration

```json
{
  "plugins": [["@babel/proposal-decorators", { "version": "2022-03" }]]
}
```

Both the `2022-03` and `2021-12` version are affected. The legacy transform does not throw.

### Current and expected behavior

Current: Babel throws "cannot turn ClassExpression to a statement".

Expected: It should be transformed or if not, provide a better error message.

### Environment

REPL

### Possible solution

_No response_

### Additional context

_No response_


Hints:
Hey @JLHwung! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant [Slack community](https://babeljs.slack.com) that typically always has someone willing to help. You can sign-up [here](https://slack.babeljs.io/) for an invite.

Patch:
diff --git a/packages/babel-plugin-proposal-decorators/src/transformer-2022-03.ts b/packages/babel-plugin-proposal-decorators/src/transformer-2022-03.ts
--- a/packages/babel-plugin-proposal-decorators/src/transformer-2022-03.ts
+++ b/packages/babel-plugin-proposal-decorators/src/transformer-2022-03.ts
@@ -937,7 +937,12 @@ function transformClass(
         class extends ${state.addHelper("identity")} {}
       ` as t.ClassExpression;
       staticsClass.body.body = [
-        t.staticBlock([t.toStatement(path.node, false)]),
+        t.staticBlock([
+          t.toStatement(originalClass, true) ||
+            // If toStatement returns false, originalClass must be an anonymous ClassExpression,
+            // because `export default @dec ...` has been handled in the export visitor before.
+            t.expressionStatement(originalClass as t.ClassExpression),
+        ]),
         ...statics,
       ];
 
diff --git a/packages/babel-plugin-proposal-object-rest-spread/src/index.ts b/packages/babel-plugin-proposal-object-rest-spread/src/index.ts
--- a/packages/babel-plugin-proposal-object-rest-spread/src/index.ts
+++ b/packages/babel-plugin-proposal-object-rest-spread/src/index.ts
@@ -531,7 +531,7 @@ export default declare((api, opts: Options) => {
           nodeWithoutSpread.right = t.identifier(refName);
           nodes.push(t.expressionStatement(nodeWithoutSpread));
           nodes.push(
-            t.toStatement(
+            t.expressionStatement(
               t.assignmentExpression("=", argument, callExpression),
             ),
           );
diff --git a/packages/babel-plugin-transform-jscript/src/index.ts b/packages/babel-plugin-transform-jscript/src/index.ts
--- a/packages/babel-plugin-transform-jscript/src/index.ts
+++ b/packages/babel-plugin-transform-jscript/src/index.ts
@@ -19,7 +19,7 @@ export default declare(api => {
                 null,
                 [],
                 t.blockStatement([
-                  // @ts-expect-error fixme: t.toStatement may return false
+                  // @ts-expect-error t.toStatement must return a FunctionDeclaration if node.id is defined
                   t.toStatement(node),
                   t.returnStatement(t.cloneNode(node.id)),
                 ]),


Test patch:
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/input.js
@@ -0,0 +1,12 @@
+const dec = () => {};
+const A = @dec class A { static {} }
+const B = @dec class C { static {} }
+const D = @dec class { static {} }
+const E = (@dec class { static {} }, 123);
+const F = [@dec class G { static {} }, @dec class { static {} }];
+const H = @dec class extends I { static {} };
+const J = @dec class K extends L { static {} };
+
+function classFactory() {
+  return @dec class { static {} }
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes--to-es2015/expressions-static-blocks/output.js
@@ -0,0 +1,67 @@
+var _initClass, _A, _temp, _initClass2, _C, _temp2, _initClass3, _D, _temp3, _initClass4, _decorated_class, _temp4, _class2, _initClass5, _G, _temp5, _initClass6, _decorated_class2, _temp6, _class3, _initClass7, _H, _temp7, _initClass8, _K, _temp8;
+const dec = () => {};
+const A = (new (_temp = class extends babelHelpers.identity {
+  constructor() {
+    super(_A), (() => {})(), _initClass();
+  }
+}, (() => {
+  class A {}
+  [_A, _initClass] = babelHelpers.applyDecs(A, [], [dec]);
+})(), _temp)(), _A);
+const B = (new (_temp2 = class extends babelHelpers.identity {
+  constructor() {
+    super(_C), (() => {})(), _initClass2();
+  }
+}, (() => {
+  class C {}
+  [_C, _initClass2] = babelHelpers.applyDecs(C, [], [dec]);
+})(), _temp2)(), _C);
+const D = (new (_temp3 = class extends babelHelpers.identity {
+  constructor() {
+    super(_D), (() => {})(), _initClass3();
+  }
+}, (() => {
+  class D {}
+  [_D, _initClass3] = babelHelpers.applyDecs(D, [], [dec]);
+})(), _temp3)(), _D);
+const E = ((new (_temp4 = class extends babelHelpers.identity {
+  constructor() {
+    super(_decorated_class), (() => {})(), _initClass4();
+  }
+}, (_class2 = class {}, [_decorated_class, _initClass4] = babelHelpers.applyDecs(_class2, [], [dec])), _temp4)(), _decorated_class), 123);
+const F = [(new (_temp5 = class extends babelHelpers.identity {
+  constructor() {
+    super(_G), (() => {})(), _initClass5();
+  }
+}, (() => {
+  class G {}
+  [_G, _initClass5] = babelHelpers.applyDecs(G, [], [dec]);
+})(), _temp5)(), _G), (new (_temp6 = class extends babelHelpers.identity {
+  constructor() {
+    super(_decorated_class2), (() => {})(), _initClass6();
+  }
+}, (_class3 = class {}, [_decorated_class2, _initClass6] = babelHelpers.applyDecs(_class3, [], [dec])), _temp6)(), _decorated_class2)];
+const H = (new (_temp7 = class extends babelHelpers.identity {
+  constructor() {
+    super(_H), (() => {})(), _initClass7();
+  }
+}, (() => {
+  class H extends I {}
+  [_H, _initClass7] = babelHelpers.applyDecs(H, [], [dec]);
+})(), _temp7)(), _H);
+const J = (new (_temp8 = class extends babelHelpers.identity {
+  constructor() {
+    super(_K), (() => {})(), _initClass8();
+  }
+}, (() => {
+  class K extends L {}
+  [_K, _initClass8] = babelHelpers.applyDecs(K, [], [dec]);
+})(), _temp8)(), _K);
+function classFactory() {
+  var _initClass9, _decorated_class3, _temp9, _class5;
+  return new (_temp9 = class extends babelHelpers.identity {
+    constructor() {
+      super(_decorated_class3), (() => {})(), _initClass9();
+    }
+  }, (_class5 = class {}, [_decorated_class3, _initClass9] = babelHelpers.applyDecs(_class5, [], [dec])), _temp9)(), _decorated_class3;
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/input.js
@@ -0,0 +1,12 @@
+const dec = () => {};
+const A = @dec class A { static {} }
+const B = @dec class C { static {} }
+const D = @dec class { static {} }
+const E = (@dec class { static {} }, 123);
+const F = [@dec class G { static {} }, @dec class { static {} }];
+const H = @dec class extends I { static {} };
+const J = @dec class K extends L { static {} };
+
+function classFactory() {
+  return @dec class { static {} }
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions-static-blocks/output.js
@@ -0,0 +1,112 @@
+var _initClass, _A, _initClass2, _C, _initClass3, _D, _initClass4, _decorated_class, _initClass5, _G, _initClass6, _decorated_class2, _initClass7, _H, _initClass8, _K;
+const dec = () => {};
+const A = (new class extends babelHelpers.identity {
+  static {
+    class A {
+      static {
+        [_A, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_A), (() => {})(), _initClass();
+  }
+}(), _A);
+const B = (new class extends babelHelpers.identity {
+  static {
+    class C {
+      static {
+        [_C, _initClass2] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_C), (() => {})(), _initClass2();
+  }
+}(), _C);
+const D = (new class extends babelHelpers.identity {
+  static {
+    class D {
+      static {
+        [_D, _initClass3] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_D), (() => {})(), _initClass3();
+  }
+}(), _D);
+const E = ((new class extends babelHelpers.identity {
+  static {
+    (class {
+      static {
+        [_decorated_class, _initClass4] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    });
+  }
+  constructor() {
+    super(_decorated_class), (() => {})(), _initClass4();
+  }
+}(), _decorated_class), 123);
+const F = [(new class extends babelHelpers.identity {
+  static {
+    class G {
+      static {
+        [_G, _initClass5] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_G), (() => {})(), _initClass5();
+  }
+}(), _G), (new class extends babelHelpers.identity {
+  static {
+    (class {
+      static {
+        [_decorated_class2, _initClass6] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    });
+  }
+  constructor() {
+    super(_decorated_class2), (() => {})(), _initClass6();
+  }
+}(), _decorated_class2)];
+const H = (new class extends babelHelpers.identity {
+  static {
+    class H extends I {
+      static {
+        [_H, _initClass7] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_H), (() => {})(), _initClass7();
+  }
+}(), _H);
+const J = (new class extends babelHelpers.identity {
+  static {
+    class K extends L {
+      static {
+        [_K, _initClass8] = babelHelpers.applyDecs(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_K), (() => {})(), _initClass8();
+  }
+}(), _K);
+function classFactory() {
+  var _initClass9, _decorated_class3;
+  return new class extends babelHelpers.identity {
+    static {
+      (class {
+        static {
+          [_decorated_class3, _initClass9] = babelHelpers.applyDecs(this, [], [dec]);
+        }
+      });
+    }
+    constructor() {
+      super(_decorated_class3), (() => {})(), _initClass9();
+    }
+  }(), _decorated_class3;
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/input.js
@@ -0,0 +1,12 @@
+const dec = () => {};
+const A = @dec class A { static {} }
+const B = @dec class C { static {} }
+const D = @dec class { static {} }
+const E = (@dec class { static {} }, 123);
+const F = [@dec class G { static {} }, @dec class { static {} }];
+const H = @dec class extends I { static {} };
+const J = @dec class K extends L { static {} };
+
+function classFactory() {
+  return @dec class { static {} }
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes--to-es2015/expressions-static-blocks/output.js
@@ -0,0 +1,67 @@
+var _initClass, _A, _temp, _initClass2, _C, _temp2, _initClass3, _D, _temp3, _initClass4, _decorated_class, _temp4, _class2, _initClass5, _G, _temp5, _initClass6, _decorated_class2, _temp6, _class3, _initClass7, _H, _temp7, _initClass8, _K, _temp8;
+const dec = () => {};
+const A = (new (_temp = class extends babelHelpers.identity {
+  constructor() {
+    super(_A), (() => {})(), _initClass();
+  }
+}, (() => {
+  class A {}
+  [_A, _initClass] = babelHelpers.applyDecs2203(A, [], [dec]);
+})(), _temp)(), _A);
+const B = (new (_temp2 = class extends babelHelpers.identity {
+  constructor() {
+    super(_C), (() => {})(), _initClass2();
+  }
+}, (() => {
+  class C {}
+  [_C, _initClass2] = babelHelpers.applyDecs2203(C, [], [dec]);
+})(), _temp2)(), _C);
+const D = (new (_temp3 = class extends babelHelpers.identity {
+  constructor() {
+    super(_D), (() => {})(), _initClass3();
+  }
+}, (() => {
+  class D {}
+  [_D, _initClass3] = babelHelpers.applyDecs2203(D, [], [dec]);
+})(), _temp3)(), _D);
+const E = ((new (_temp4 = class extends babelHelpers.identity {
+  constructor() {
+    super(_decorated_class), (() => {})(), _initClass4();
+  }
+}, (_class2 = class {}, [_decorated_class, _initClass4] = babelHelpers.applyDecs2203(_class2, [], [dec])), _temp4)(), _decorated_class), 123);
+const F = [(new (_temp5 = class extends babelHelpers.identity {
+  constructor() {
+    super(_G), (() => {})(), _initClass5();
+  }
+}, (() => {
+  class G {}
+  [_G, _initClass5] = babelHelpers.applyDecs2203(G, [], [dec]);
+})(), _temp5)(), _G), (new (_temp6 = class extends babelHelpers.identity {
+  constructor() {
+    super(_decorated_class2), (() => {})(), _initClass6();
+  }
+}, (_class3 = class {}, [_decorated_class2, _initClass6] = babelHelpers.applyDecs2203(_class3, [], [dec])), _temp6)(), _decorated_class2)];
+const H = (new (_temp7 = class extends babelHelpers.identity {
+  constructor() {
+    super(_H), (() => {})(), _initClass7();
+  }
+}, (() => {
+  class H extends I {}
+  [_H, _initClass7] = babelHelpers.applyDecs2203(H, [], [dec]);
+})(), _temp7)(), _H);
+const J = (new (_temp8 = class extends babelHelpers.identity {
+  constructor() {
+    super(_K), (() => {})(), _initClass8();
+  }
+}, (() => {
+  class K extends L {}
+  [_K, _initClass8] = babelHelpers.applyDecs2203(K, [], [dec]);
+})(), _temp8)(), _K);
+function classFactory() {
+  var _initClass9, _decorated_class3, _temp9, _class5;
+  return new (_temp9 = class extends babelHelpers.identity {
+    constructor() {
+      super(_decorated_class3), (() => {})(), _initClass9();
+    }
+  }, (_class5 = class {}, [_decorated_class3, _initClass9] = babelHelpers.applyDecs2203(_class5, [], [dec])), _temp9)(), _decorated_class3;
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/input.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/input.js
@@ -0,0 +1,12 @@
+const dec = () => {};
+const A = @dec class A { static {} }
+const B = @dec class C { static {} }
+const D = @dec class { static {} }
+const E = (@dec class { static {} }, 123);
+const F = [@dec class G { static {} }, @dec class { static {} }];
+const H = @dec class extends I { static {} };
+const J = @dec class K extends L { static {} };
+
+function classFactory() {
+  return @dec class { static {} }
+}
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2022-03-classes/expressions-static-blocks/output.js
@@ -0,0 +1,112 @@
+var _initClass, _A, _initClass2, _C, _initClass3, _D, _initClass4, _decorated_class, _initClass5, _G, _initClass6, _decorated_class2, _initClass7, _H, _initClass8, _K;
+const dec = () => {};
+const A = (new class extends babelHelpers.identity {
+  static {
+    class A {
+      static {
+        [_A, _initClass] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_A), (() => {})(), _initClass();
+  }
+}(), _A);
+const B = (new class extends babelHelpers.identity {
+  static {
+    class C {
+      static {
+        [_C, _initClass2] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_C), (() => {})(), _initClass2();
+  }
+}(), _C);
+const D = (new class extends babelHelpers.identity {
+  static {
+    class D {
+      static {
+        [_D, _initClass3] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_D), (() => {})(), _initClass3();
+  }
+}(), _D);
+const E = ((new class extends babelHelpers.identity {
+  static {
+    (class {
+      static {
+        [_decorated_class, _initClass4] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    });
+  }
+  constructor() {
+    super(_decorated_class), (() => {})(), _initClass4();
+  }
+}(), _decorated_class), 123);
+const F = [(new class extends babelHelpers.identity {
+  static {
+    class G {
+      static {
+        [_G, _initClass5] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_G), (() => {})(), _initClass5();
+  }
+}(), _G), (new class extends babelHelpers.identity {
+  static {
+    (class {
+      static {
+        [_decorated_class2, _initClass6] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    });
+  }
+  constructor() {
+    super(_decorated_class2), (() => {})(), _initClass6();
+  }
+}(), _decorated_class2)];
+const H = (new class extends babelHelpers.identity {
+  static {
+    class H extends I {
+      static {
+        [_H, _initClass7] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_H), (() => {})(), _initClass7();
+  }
+}(), _H);
+const J = (new class extends babelHelpers.identity {
+  static {
+    class K extends L {
+      static {
+        [_K, _initClass8] = babelHelpers.applyDecs2203(this, [], [dec]);
+      }
+    }
+  }
+  constructor() {
+    super(_K), (() => {})(), _initClass8();
+  }
+}(), _K);
+function classFactory() {
+  var _initClass9, _decorated_class3;
+  return new class extends babelHelpers.identity {
+    static {
+      (class {
+        static {
+          [_decorated_class3, _initClass9] = babelHelpers.applyDecs2203(this, [], [dec]);
+        }
+      });
+    }
+    constructor() {
+      super(_decorated_class3), (() => {})(), _initClass9();
+    }
+  }(), _decorated_class3;
+}