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
+};