Repository: facebook/react
Pull request: [compiler] Errors for eval(), with statments, class declarations


* Error for `eval()`
* More specific error message for `with (expr) { ... }` syntax
* More specific error message for class declarations

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

Changed files:
filename: compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
patch: @@ -1355,13 +1355,45 @@ function lowerStatement(
 
       return;
     }
+    case 'WithStatement': {
+      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,
+        loc: stmtPath.node.loc ?? null,
+        suggestions: null,
+      });
+      lowerValueToTemporary(builder, {
+        kind: 'UnsupportedNode',
+        loc: stmtPath.node.loc ?? GeneratedSource,
+        node: stmtPath.node,
+      });
+      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
+       */
+      builder.errors.push({
+        reason: `Support nested class declarations`,
+        severity: ErrorSeverity.Todo,
+        loc: stmtPath.node.loc ?? null,
+        suggestions: null,
+      });
+      lowerValueToTemporary(builder, {
+        kind: 'UnsupportedNode',
+        loc: stmtPath.node.loc ?? GeneratedSource,
+        node: stmtPath.node,
+      });
+      return;
+    }
     case 'TypeAlias':
     case 'TSInterfaceDeclaration':
     case 'TSTypeAliasDeclaration': {
       // We do not preserve type annotations/syntax through transformation
       return;
     }
-    case 'ClassDeclaration':
     case 'DeclareClass':
     case 'DeclareExportAllDeclaration':
     case 'DeclareExportDeclaration':
@@ -1384,8 +1416,7 @@ function lowerStatement(
     case 'TSExportAssignment':
     case 'TSImportEqualsDeclaration':
     case 'TSModuleDeclaration':
-    case 'TSNamespaceExportDeclaration':
-    case 'WithStatement': {
+    case 'TSNamespaceExportDeclaration': {
       builder.errors.push({
         reason: `(BuildHIR::lowerStatement) Handle ${stmtPath.type} statements`,
         severity: ErrorSeverity.Todo,
@@ -3502,6 +3533,16 @@ function lowerIdentifier(
       return place;
     }
     default: {
+      if (binding.kind === 'Global' && binding.name === 'eval') {
+        builder.errors.push({
+          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,
+          loc: exprPath.node.loc ?? null,
+          suggestions: null,
+        });
+      }
       return lowerValueToTemporary(builder, {
         kind: 'LoadGlobal',
         binding,

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.expect.md
patch: @@ -0,0 +1,24 @@
+
+## Input
+
+```javascript
+function Component(props) {
+  eval('props.x = true');
+  return <div />;
+}
+
+```
+
+
+## Error
+
+```
+  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)
+  3 |   return <div />;
+  4 | }
+  5 |
+```
+          
+      
\ No newline at end of file

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.js
patch: @@ -0,0 +1,4 @@
+function Component(props) {
+  eval('props.x = true');
+  return <div />;
+}

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: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10)
+Todo: Support nested class declarations (5:10)
 
 Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)