[compiler] Add CompilerError.UnsupportedJS variant (#33750)

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
This commit is contained in:
Joseph Savona 2025-07-09 22:24:20 -07:00 committed by GitHub
parent 0bfa404bac
commit 96c61b7f1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 22 additions and 11 deletions

View File

@ -15,6 +15,11 @@ export enum ErrorSeverity {
* misunderstanding on the users 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,13 +246,17 @@ 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');
}
}
});
}
}

View File

@ -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,
});

View File

@ -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 |

View File

@ -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)