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>
This commit is contained in:
Rodrigo Faria 2025-03-28 15:10:32 +00:00 committed by GitHub
parent 8039f1b2a0
commit ef4bc8b4f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 176 additions and 7 deletions

View File

@ -2406,6 +2406,19 @@ function lowerExpression(
kind: 'TypeCastExpression',
value: lowerExpressionToTemporary(builder, expr.get('expression')),
typeAnnotation: typeAnnotation.node,
typeAnnotationKind: 'cast',
type: lowerType(typeAnnotation.node),
loc: exprLoc,
};
}
case 'TSSatisfiesExpression': {
let expr = exprPath as NodePath<t.TSSatisfiesExpression>;
const typeAnnotation = expr.get('typeAnnotation');
return {
kind: 'TypeCastExpression',
value: lowerExpressionToTemporary(builder, expr.get('expression')),
typeAnnotation: typeAnnotation.node,
typeAnnotationKind: 'satisfies',
type: lowerType(typeAnnotation.node),
loc: exprLoc,
};
@ -2417,6 +2430,7 @@ function lowerExpression(
kind: 'TypeCastExpression',
value: lowerExpressionToTemporary(builder, expr.get('expression')),
typeAnnotation: typeAnnotation.node,
typeAnnotationKind: 'as',
type: lowerType(typeAnnotation.node),
loc: exprLoc,
};

View File

@ -910,13 +910,21 @@ export type InstructionValue =
value: Place;
loc: SourceLocation;
}
| {
| ({
kind: 'TypeCastExpression';
value: Place;
typeAnnotation: t.FlowType | t.TSType;
type: Type;
loc: SourceLocation;
}
} & (
| {
typeAnnotation: t.FlowType;
typeAnnotationKind: 'cast';
}
| {
typeAnnotation: t.TSType;
typeAnnotationKind: 'as' | 'satisfies';
}
))
| JsxExpression
| {
kind: 'ObjectExpression';

View File

@ -2115,10 +2115,17 @@ function codegenInstructionValue(
}
case 'TypeCastExpression': {
if (t.isTSType(instrValue.typeAnnotation)) {
value = t.tsAsExpression(
codegenPlaceToExpression(cx, instrValue.value),
instrValue.typeAnnotation,
);
if (instrValue.typeAnnotationKind === 'satisfies') {
value = t.tsSatisfiesExpression(
codegenPlaceToExpression(cx, instrValue.value),
instrValue.typeAnnotation,
);
} else {
value = t.tsAsExpression(
codegenPlaceToExpression(cx, instrValue.value),
instrValue.typeAnnotation,
);
}
} else {
value = t.typeCastExpression(
codegenPlaceToExpression(cx, instrValue.value),

View File

@ -0,0 +1,71 @@
## Input
```javascript
// @enableUseTypeAnnotations
function Component(props: {id: number}) {
const x = makeArray(props.id) satisfies number[];
const y = x.at(0);
return y;
}
function makeArray<T>(x: T): Array<T> {
return [x];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{id: 42}],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime"; // @enableUseTypeAnnotations
function Component(props) {
const $ = _c(4);
let t0;
if ($[0] !== props.id) {
t0 = makeArray(props.id);
$[0] = props.id;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0 satisfies number[];
let t1;
if ($[2] !== x) {
t1 = x.at(0);
$[2] = x;
$[3] = t1;
} else {
t1 = $[3];
}
const y = t1;
return y;
}
function makeArray(x) {
const $ = _c(2);
let t0;
if ($[0] !== x) {
t0 = [x];
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ id: 42 }],
};
```
### Eval output
(kind: ok) 42

View File

@ -0,0 +1,15 @@
// @enableUseTypeAnnotations
function Component(props: {id: number}) {
const x = makeArray(props.id) satisfies number[];
const y = x.at(0);
return y;
}
function makeArray<T>(x: T): Array<T> {
return [x];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{id: 42}],
};

View File

@ -0,0 +1,41 @@
## Input
```javascript
// @enableUseTypeAnnotations
import {identity} from 'shared-runtime';
function Component(props: {id: number}) {
const x = identity(props.id);
const y = x satisfies number;
return y;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{id: 42}],
};
```
## Code
```javascript
// @enableUseTypeAnnotations
import { identity } from "shared-runtime";
function Component(props) {
const x = identity(props.id);
const y = x satisfies number;
return y;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ id: 42 }],
};
```
### Eval output
(kind: ok) 42

View File

@ -0,0 +1,13 @@
// @enableUseTypeAnnotations
import {identity} from 'shared-runtime';
function Component(props: {id: number}) {
const x = identity(props.id);
const y = x satisfies number;
return y;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{id: 42}],
};