@samitouri / QOS-React-2 / commits / ef4bc8b4f9

feat(babel-plugin-react-compiler): support satisfies operator (#32742)

Solve https://github.com/facebook/react/pull/29818 --------- Co-authored-by: Rodrigo Faria <rodrigo.faria@cartrack.com>

Rodrigo Faria committed Mar 28, 2025 at 15:10 UTC ef4bc8b4f91023afac437be9179beef350b32db3
7 files changed +176 -7
compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
+14
@@ -2406,6 +2406,19 @@ function lowerExpression(
2406 kind: 'TypeCastExpression',
2407 value: lowerExpressionToTemporary(builder, expr.get('expression')),
2408 typeAnnotation: typeAnnotation.node,
2409 + typeAnnotationKind: 'cast',
2410 + type: lowerType(typeAnnotation.node),
2411 + loc: exprLoc,
2412 + };
2413 + }
2414 + case 'TSSatisfiesExpression': {
2415 + let expr = exprPath as NodePath<t.TSSatisfiesExpression>;
2416 + const typeAnnotation = expr.get('typeAnnotation');
2417 + return {
2418 + kind: 'TypeCastExpression',
2419 + value: lowerExpressionToTemporary(builder, expr.get('expression')),
2420 + typeAnnotation: typeAnnotation.node,
2421 + typeAnnotationKind: 'satisfies',
2422 type: lowerType(typeAnnotation.node),
2423 loc: exprLoc,
2424 };
@@ -2417,6 +2430,7 @@ function lowerExpression(
2430 kind: 'TypeCastExpression',
2431 value: lowerExpressionToTemporary(builder, expr.get('expression')),
2432 typeAnnotation: typeAnnotation.node,
2433 + typeAnnotationKind: 'as',
2434 type: lowerType(typeAnnotation.node),
2435 loc: exprLoc,
2436 };
compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
+11 -3
@@ -910,13 +910,21 @@ export type InstructionValue =
910 value: Place;
911 loc: SourceLocation;
912 }
913 - | {
913 + | ({
914 kind: 'TypeCastExpression';
915 value: Place;
916 - typeAnnotation: t.FlowType | t.TSType;
916 type: Type;
917 loc: SourceLocation;
919 - }
918 + } & (
919 + | {
920 + typeAnnotation: t.FlowType;
921 + typeAnnotationKind: 'cast';
922 + }
923 + | {
924 + typeAnnotation: t.TSType;
925 + typeAnnotationKind: 'as' | 'satisfies';
926 + }
927 + ))
928 | JsxExpression
929 | {
930 kind: 'ObjectExpression';
compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts
+11 -4
@@ -2115,10 +2115,17 @@ function codegenInstructionValue(
2115 }
2116 case 'TypeCastExpression': {
2117 if (t.isTSType(instrValue.typeAnnotation)) {
2118 - value = t.tsAsExpression(
2119 - codegenPlaceToExpression(cx, instrValue.value),
2120 - instrValue.typeAnnotation,
2121 - );
2118 + if (instrValue.typeAnnotationKind === 'satisfies') {
2119 + value = t.tsSatisfiesExpression(
2120 + codegenPlaceToExpression(cx, instrValue.value),
2121 + instrValue.typeAnnotation,
2122 + );
2123 + } else {
2124 + value = t.tsAsExpression(
2125 + codegenPlaceToExpression(cx, instrValue.value),
2126 + instrValue.typeAnnotation,
2127 + );
2128 + }
2129 } else {
2130 value = t.typeCastExpression(
2131 codegenPlaceToExpression(cx, instrValue.value),
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-annotations/type-annotation-satisfies-array.expect.md new
+71
@@ -0,0 +1,71 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @enableUseTypeAnnotations
6 +function Component(props: {id: number}) {
7 + const x = makeArray(props.id) satisfies number[];
8 + const y = x.at(0);
9 + return y;
10 +}
11 +
12 +function makeArray<T>(x: T): Array<T> {
13 + return [x];
14 +}
15 +
16 +export const FIXTURE_ENTRYPOINT = {
17 + fn: Component,
18 + params: [{id: 42}],
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { c as _c } from "react/compiler-runtime"; // @enableUseTypeAnnotations
27 +function Component(props) {
28 + const $ = _c(4);
29 + let t0;
30 + if ($[0] !== props.id) {
31 + t0 = makeArray(props.id);
32 + $[0] = props.id;
33 + $[1] = t0;
34 + } else {
35 + t0 = $[1];
36 + }
37 + const x = t0 satisfies number[];
38 + let t1;
39 + if ($[2] !== x) {
40 + t1 = x.at(0);
41 + $[2] = x;
42 + $[3] = t1;
43 + } else {
44 + t1 = $[3];
45 + }
46 + const y = t1;
47 + return y;
48 +}
49 +
50 +function makeArray(x) {
51 + const $ = _c(2);
52 + let t0;
53 + if ($[0] !== x) {
54 + t0 = [x];
55 + $[0] = x;
56 + $[1] = t0;
57 + } else {
58 + t0 = $[1];
59 + }
60 + return t0;
61 +}
62 +
63 +export const FIXTURE_ENTRYPOINT = {
64 + fn: Component,
65 + params: [{ id: 42 }],
66 +};
67 +
68 +```
69 +
70 +### Eval output
71 +(kind: ok) 42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-annotations/type-annotation-satisfies-array.ts new
+15
@@ -0,0 +1,15 @@
1 +// @enableUseTypeAnnotations
2 +function Component(props: {id: number}) {
3 + const x = makeArray(props.id) satisfies number[];
4 + const y = x.at(0);
5 + return y;
6 +}
7 +
8 +function makeArray<T>(x: T): Array<T> {
9 + return [x];
10 +}
11 +
12 +export const FIXTURE_ENTRYPOINT = {
13 + fn: Component,
14 + params: [{id: 42}],
15 +};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-annotations/type-annotation-satisfies-number.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @enableUseTypeAnnotations
6 +import {identity} from 'shared-runtime';
7 +
8 +function Component(props: {id: number}) {
9 + const x = identity(props.id);
10 + const y = x satisfies number;
11 + return y;
12 +}
13 +
14 +export const FIXTURE_ENTRYPOINT = {
15 + fn: Component,
16 + params: [{id: 42}],
17 +};
18 +
19 +```
20 +
21 +## Code
22 +
23 +```javascript
24 +// @enableUseTypeAnnotations
25 +import { identity } from "shared-runtime";
26 +
27 +function Component(props) {
28 + const x = identity(props.id);
29 + const y = x satisfies number;
30 + return y;
31 +}
32 +
33 +export const FIXTURE_ENTRYPOINT = {
34 + fn: Component,
35 + params: [{ id: 42 }],
36 +};
37 +
38 +```
39 +
40 +### Eval output
41 +(kind: ok) 42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-annotations/type-annotation-satisfies-number.ts new
+13
@@ -0,0 +1,13 @@
1 +// @enableUseTypeAnnotations
2 +import {identity} from 'shared-runtime';
3 +
4 +function Component(props: {id: number}) {
5 + const x = identity(props.id);
6 + const y = x satisfies number;
7 + return y;
8 +}
9 +
10 +export const FIXTURE_ENTRYPOINT = {
11 + fn: Component,
12 + params: [{id: 42}],
13 +};