mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir] Parse and codegen FunctionExpression
This commit is contained in:
@@ -1148,6 +1148,22 @@ function lowerExpression(
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "FunctionExpression": {
|
||||
const expr = exprPath as NodePath<t.FunctionExpression>;
|
||||
const name: string | null = expr.get("id")?.node?.name ?? null;
|
||||
const body = expr.get("body").node;
|
||||
const params: Array<string> = expr.get("params").map((p) => {
|
||||
todoInvariant(p.isIdentifier(), "handle non identifier params");
|
||||
return p.node.name;
|
||||
});
|
||||
return {
|
||||
kind: "FunctionExpression",
|
||||
name,
|
||||
body,
|
||||
params,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
todo(`lowerExpression(${exprNode.type})`);
|
||||
// assertExhaustive(
|
||||
|
||||
@@ -498,6 +498,13 @@ export function codegenInstructionValue(
|
||||
value = codegenPlace(temp, instrValue);
|
||||
break;
|
||||
}
|
||||
case "FunctionExpression": {
|
||||
const id =
|
||||
instrValue.name !== null ? t.identifier(instrValue.name) : null;
|
||||
const params = instrValue.params.map((p) => t.identifier(p));
|
||||
value = t.functionExpression(id, params, instrValue.body);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
instrValue,
|
||||
|
||||
@@ -309,6 +309,12 @@ export type InstructionData =
|
||||
| { kind: "ComputedStore"; object: Place; property: Place; value: Place }
|
||||
// load `object[index]` - like PropertyLoad but with a dynamic property
|
||||
| { kind: "ComputedLoad"; object: Place; property: Place }
|
||||
| {
|
||||
kind: "FunctionExpression";
|
||||
name: string | null;
|
||||
params: Array<string>;
|
||||
body: t.BlockStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch-all for statements such as type imports, nested class declarations, etc
|
||||
|
||||
@@ -290,6 +290,12 @@ export function printInstructionValue(instrValue: InstructionValue): string {
|
||||
)}] = ${printPlace(instrValue.value)}`;
|
||||
break;
|
||||
}
|
||||
case "FunctionExpression": {
|
||||
const params = instrValue.params.join(",");
|
||||
const body = generate(instrValue.body).code;
|
||||
value = `Function ${instrValue.name}(${params}){${body}}`;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
instrValue,
|
||||
|
||||
@@ -89,6 +89,7 @@ export function* eachInstructionValueOperand(
|
||||
}
|
||||
case "OtherStatement":
|
||||
case "Primitive":
|
||||
case "FunctionExpression":
|
||||
case "JSXText": {
|
||||
break;
|
||||
}
|
||||
@@ -175,6 +176,7 @@ export function mapInstructionOperands(
|
||||
}
|
||||
case "OtherStatement":
|
||||
case "Primitive":
|
||||
case "FunctionExpression":
|
||||
case "JSXText": {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -551,6 +551,12 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
lvalueEffect = Effect.Store;
|
||||
break;
|
||||
}
|
||||
case "FunctionExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
effectKind = Effect.Read;
|
||||
lvalueEffect = Effect.Store;
|
||||
break;
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
// TODO check that value must be a primitive, or make conditional based on the operator
|
||||
valueKind = ValueKind.Immutable;
|
||||
|
||||
@@ -173,6 +173,7 @@ function mayAllocate(value: InstructionValue): boolean {
|
||||
case "NewExpression":
|
||||
case "ObjectExpression":
|
||||
case "OtherStatement":
|
||||
case "FunctionExpression":
|
||||
case "UnaryExpression": {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,6 +313,7 @@ function valueKind(value: InstructionValue): DeclKind {
|
||||
case "JsxFragment":
|
||||
case "NewExpression":
|
||||
case "ObjectExpression":
|
||||
case "FunctionExpression":
|
||||
case "OtherStatement":
|
||||
case "UnaryExpression": {
|
||||
return DeclKind.Dynamic;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
let x = function (a) {
|
||||
a.foo();
|
||||
};
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.useMemoCache();
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = function (a) {
|
||||
a.foo();
|
||||
};
|
||||
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function component() {
|
||||
let x = function (a) {
|
||||
a.foo();
|
||||
};
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user