mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support TypeCastExpression
Support TypeCastExpressions — `(x: TypeAnnotation)`. This is pretty straightforward, it's semantically identical to a raw identifier. One catch is that our prettier config is hard-coded to use the babel-ts parser, i wasn't sure how to make that dynamic based on the file extension so for now i just ignored .flow.js files in our pretter config.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/packages/demo-*
|
||||
**/dist
|
||||
**/__tests__/fixtures/**/*.expect.md
|
||||
**/__tests__/fixtures/**/*.flow.js
|
||||
**/.next
|
||||
test262/
|
||||
*.md
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function runReactForgetBabelPlugin(
|
||||
ast: result.ast,
|
||||
code: prettier.format(result.code, {
|
||||
semi: true,
|
||||
parser: "babel-ts",
|
||||
parser: language === "typescript" ? "babel-ts" : "flow",
|
||||
}),
|
||||
map: result.map,
|
||||
};
|
||||
|
||||
@@ -1386,6 +1386,15 @@ function lowerExpression(
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
let expr = exprPath as NodePath<t.TypeCastExpression>;
|
||||
return {
|
||||
kind: "TypeCastExpression",
|
||||
value: lowerExpressionToPlace(builder, expr.get("expression")),
|
||||
type: expr.get("typeAnnotation").node,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`,
|
||||
|
||||
@@ -416,6 +416,7 @@ export type InstructionData =
|
||||
args: Array<Place>;
|
||||
}
|
||||
| { kind: "UnaryExpression"; operator: string; value: Place }
|
||||
| { kind: "TypeCastExpression"; value: Place; type: t.TypeAnnotation }
|
||||
| {
|
||||
kind: "JsxExpression";
|
||||
tag: Place;
|
||||
|
||||
@@ -259,6 +259,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
value = JSON.stringify(instrValue.value);
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
value = `TypeCast ${printPlace(instrValue.value)}`;
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
const propItems = [];
|
||||
for (const attribute of instrValue.props) {
|
||||
|
||||
@@ -123,6 +123,10 @@ export function* eachInstructionValueOperand(
|
||||
yield instrValue.tag;
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
yield instrValue.value;
|
||||
break;
|
||||
}
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
case "JSXText": {
|
||||
@@ -243,6 +247,10 @@ export function mapInstructionOperands(
|
||||
instrValue.tag = fn(instrValue.tag);
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
instrValue.value = fn(instrValue.value);
|
||||
break;
|
||||
}
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
case "JSXText": {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
import {
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
LValue,
|
||||
Place,
|
||||
} from "../HIR/HIR";
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
|
||||
export type AliasSet = Set<Identifier>;
|
||||
|
||||
@@ -44,6 +44,10 @@ function inferInstr(instr: Instruction, state: AliasAnalyser) {
|
||||
alias = instrValue.object;
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
alias = instrValue.value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -693,6 +693,20 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
env.define(lvalue.place, instrValue);
|
||||
continue;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
// A type cast expression has no effect at runtime, so it's equivalent to a raw
|
||||
// identifier:
|
||||
// ```
|
||||
// x = (y: type) // is equivalent to...
|
||||
// x = y
|
||||
// ```
|
||||
env.initialize(instrValue, env.kind(instrValue.value));
|
||||
env.reference(instrValue.value, Effect.Read);
|
||||
const lvalue = instr.lvalue;
|
||||
lvalue.place.effect = Effect.Mutate;
|
||||
env.alias(lvalue.place, instrValue.value);
|
||||
continue;
|
||||
}
|
||||
case "Identifier": {
|
||||
env.reference(instrValue, Effect.Read);
|
||||
const lvalue = instr.lvalue;
|
||||
|
||||
@@ -672,6 +672,13 @@ function codegenInstructionValue(
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
value = t.typeCastExpression(
|
||||
codegenInstructionValue(cx, instrValue.value),
|
||||
instrValue.type
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "LogicalExpression": {
|
||||
value = createLogicalExpression(
|
||||
instrValue.loc,
|
||||
|
||||
@@ -167,6 +167,7 @@ function isMutable({ id }: Instruction, place: Place): boolean {
|
||||
|
||||
function mayAllocate(value: InstructionValue): boolean {
|
||||
switch (value.kind) {
|
||||
case "TypeCastExpression":
|
||||
case "BinaryExpression":
|
||||
case "Identifier":
|
||||
case "PropertyLoad":
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
type Foo = {bar: string};
|
||||
function Component(props) {
|
||||
const x = {bar: props.bar};
|
||||
const y = (x: Foo);
|
||||
y.bar = 'hello';
|
||||
const z = (y: Foo);
|
||||
return z;
|
||||
}
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
type Foo = { bar: string };
|
||||
function Component(props) {
|
||||
const $ = React.useMemoCache();
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let y;
|
||||
if (c_0) {
|
||||
const x = { bar: props.bar };
|
||||
y = (x: Foo);
|
||||
y.bar = "hello";
|
||||
$[0] = props.bar;
|
||||
$[1] = y;
|
||||
} else {
|
||||
y = $[1];
|
||||
}
|
||||
|
||||
const z = (y: Foo);
|
||||
return z;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// @flow
|
||||
type Foo = {bar: string};
|
||||
function Component(props) {
|
||||
const x = {bar: props.bar};
|
||||
const y = (x: Foo);
|
||||
y.bar = 'hello';
|
||||
const z = (y: Foo);
|
||||
return z;
|
||||
}
|
||||
Reference in New Issue
Block a user