@samitouri / QOS-React-1 / commits / 4c2e457c7c

compiler: Handle TSNonNullAssertion expressions (#29218)

## Summary We ran React compiler against part of our codebase and collected compiler errors. One of the more common non-actionable errors is caused by usage of the `!` TypeScript non-null assertion operation: ``` (BuildHIR::lowerExpression) Handle TSNonNullExpression expressions ``` It seems like React Compiler _should_ be able to support this by just ignoring the syntax and using the underlying expression. I'm sure a lot of our non-null assertion usage should not exist and I understand if React Compiler does not want to support this syntax. It wasn't obvious to me if this omission was intentional or if there are future plans to use `TSNonNullExpression` as part of the compiler's analysis. If there are no future plans it seems like just ignoring it should be fine. ## How did you test this change? ```sh ❯ yarn snap --filter yarn run v1.17.3 $ yarn workspace babel-plugin-react-compiler run snap --filter $ node ../snap/dist/main.js --filter PASS non-null-assertion 1 Tests, 1 Passed, 0 Failed ```

Henry Q. Dineen committed May 22, 2024 at 18:42 UTC 4c2e457c7c820e5b4bc895735a703cdbf40f3175
3 files changed +65
compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
+4
@@ -2407,6 +2407,10 @@ function lowerExpression(
2407 loc: expr.node.loc ?? GeneratedSource,
2408 };
2409 }
2410 + case "TSNonNullExpression": {
2411 + let expr = exprPath as NodePath<t.TSNonNullExpression>;
2412 + return lowerExpression(builder, expr.get("expression"));
2413 + }
2414 default: {
2415 builder.errors.push({
2416 reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/non-null-assertion.expect.md new
+49
@@ -0,0 +1,49 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +interface ComponentProps {
6 + name?: string;
7 +}
8 +
9 +function Component(props: ComponentProps) {
10 + return props.name!.toUpperCase();
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: Component,
15 + params: [{ name: "Alice" }],
16 +};
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { c as _c } from "react/compiler-runtime";
24 +interface ComponentProps {
25 + name?: string;
26 +}
27 +
28 +function Component(props) {
29 + const $ = _c(2);
30 + let t0;
31 + if ($[0] !== props.name) {
32 + t0 = props.name.toUpperCase();
33 + $[0] = props.name;
34 + $[1] = t0;
35 + } else {
36 + t0 = $[1];
37 + }
38 + return t0;
39 +}
40 +
41 +export const FIXTURE_ENTRYPOINT = {
42 + fn: Component,
43 + params: [{ name: "Alice" }],
44 +};
45 +
46 +```
47 +
48 +### Eval output
49 +(kind: ok) "ALICE"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/non-null-assertion.ts new
+12
@@ -0,0 +1,12 @@
1 +interface ComponentProps {
2 + name?: string;
3 +}
4 +
5 +function Component(props: ComponentProps) {
6 + return props.name!.toUpperCase();
7 +}
8 +
9 +export const FIXTURE_ENTRYPOINT = {
10 + fn: Component,
11 + params: [{ name: "Alice" }],
12 +};