Repository: facebook/react
Pull request: [compiler] Add CompilerError.UnsupportedJS variant


We use this variant for syntax we intentionally don't support: with statements, eval, and inline class declarations.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33750).
* #33753
* #33752
* #33751
* __->__ #33750
* #33748

Changed files:
filename: compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts
patch: @@ -15,6 +15,11 @@ export enum ErrorSeverity {
    * misunderstanding on the user’s part.
    */
   InvalidJS = 'InvalidJS',
+  /**
+   * JS syntax that is not supported and which we do not plan to support. Developers should
+   * rewrite to use supported forms.
+   */
+  UnsupportedJS = 'UnsupportedJS',
   /**
    * Code that breaks the rules of React.
    */
@@ -241,12 +246,16 @@ export class CompilerError extends Error {
         case ErrorSeverity.InvalidJS:
         case ErrorSeverity.InvalidReact:
         case ErrorSeverity.InvalidConfig:
+        case ErrorSeverity.UnsupportedJS: {
           return true;
+        }
         case ErrorSeverity.CannotPreserveMemoization:
-        case ErrorSeverity.Todo:
+        case ErrorSeverity.Todo: {
           return false;
-        default:
+        }
+        default: {
           assertExhaustive(detail.severity, 'Unhandled error severity');
+        }
       }
     });
   }

filename: compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
patch: @@ -1359,7 +1359,7 @@ function lowerStatement(
       builder.errors.push({
         reason: `JavaScript 'with' syntax is not supported`,
         description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`,
-        severity: ErrorSeverity.InvalidJS,
+        severity: ErrorSeverity.UnsupportedJS,
         loc: stmtPath.node.loc ?? null,
         suggestions: null,
       });
@@ -1371,13 +1371,15 @@ function lowerStatement(
       return;
     }
     case 'ClassDeclaration': {
-      /*
-       * We can in theory support nested classes, similarly to functions where we track values
-       * captured by the class and consider mutations of the instances to mutate the class itself
+      /**
+       * In theory we could support inline class declarations, but this is rare enough in practice
+       * and complex enough to support that we don't anticipate supporting anytime soon. Developers
+       * are encouraged to lift classes out of component/hook declarations.
        */
       builder.errors.push({
-        reason: `Support nested class declarations`,
-        severity: ErrorSeverity.Todo,
+        reason: 'Inline `class` declarations are not supported',
+        description: `Move class declarations outside of components/hooks`,
+        severity: ErrorSeverity.UnsupportedJS,
         loc: stmtPath.node.loc ?? null,
         suggestions: null,
       });
@@ -3560,7 +3562,7 @@ function lowerIdentifier(
           reason: `The 'eval' function is not supported`,
           description:
             'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler',
-          severity: ErrorSeverity.InvalidJS,
+          severity: ErrorSeverity.UnsupportedJS,
           loc: exprPath.node.loc ?? null,
           suggestions: null,
         });

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.expect.md
patch: @@ -15,7 +15,7 @@ function Component(props) {
 ```
   1 | function Component(props) {
 > 2 |   eval('props.x = true');
-    |   ^^^^ InvalidJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
+    |   ^^^^ UnsupportedJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
   3 |   return <div />;
   4 | }
   5 |

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md
patch: @@ -84,7 +84,7 @@ let moduleLocal = false;
 > 3 |   var x = [];
     |   ^^^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
 
-Todo: Support nested class declarations (5:10)
+UnsupportedJS: Inline `class` declarations are not supported. Move class declarations outside of components/hooks (5:10)
 
 Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)