BuildHIR lowers FunctionDecl instead of rewriting to FuncExpr
We were modifying the Babel AST as a shortcut to lowering function declarations, instead we can explicitly lower them equivalently to a `let <id> = <function-expression>`.
Joe Savona committed
Nov 16, 2023 at 15:41 UTC
8176ebb5468a492710ca3482015c7b172912f279
4 files changed
+30
-36
compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+24
-34
@@ -930,36 +930,18 @@ function lowerStatement(
930
});
931
const id = stmt.get("id") as NodePath<t.Identifier>;
932
933
- /*
934
- * Desugar FunctionDeclaration to FunctionExpression.
935
- *
936
- * For example:
937
- * function foo() {};
938
- * becomes
939
- * let foo = function foo() {};
940
- */
941
- const desugared = stmt.replaceWith(
942
- t.variableDeclaration("let", [
943
- t.variableDeclarator(
944
- id.node,
945
- t.functionExpression(
946
- id.node,
947
- stmt.node.params,
948
- stmt.node.body,
949
- stmt.node.generator,
950
- stmt.node.async
951
- )
952
- ),
953
- ])
933
+ const fn = lowerValueToTemporary(
934
+ builder,
935
+ lowerFunctionToValue(builder, stmt)
936
);
955
- CompilerError.invariant(desugared.length === 1, {
956
- reason:
957
- "only one declaration is created from desugaring function declaration",
958
- description: null,
959
- loc: stmt.node.loc ?? null,
960
- suggestions: null,
961
- });
962
- lowerStatement(builder, desugared.at(0)!);
937
+ lowerAssignment(
938
+ builder,
939
+ stmt.node.loc ?? GeneratedSource,
940
+ InstructionKind.Let,
941
+ id,
942
+ fn
943
+ );
944
+
945
return;
946
}
947
case "ForOfStatement": {
@@ -2042,7 +2024,7 @@ function lowerExpression(
2024
const expr = exprPath as NodePath<
2025
t.FunctionExpression | t.ArrowFunctionExpression
2026
>;
2045
- return lowerFunctionExpression(builder, expr);
2027
+ return lowerFunctionToValue(builder, expr);
2028
}
2029
case "TaggedTemplateExpression": {
2030
const expr = exprPath as NodePath<t.TaggedTemplateExpression>;
@@ -2990,9 +2972,11 @@ function trimJsxText(original: string): string | null {
2972
}
2973
}
2974
2993
-function lowerFunctionExpression(
2975
+function lowerFunctionToValue(
2976
builder: HIRBuilder,
2995
- expr: NodePath<t.FunctionExpression | t.ArrowFunctionExpression>
2977
+ expr: NodePath<
2978
+ t.FunctionExpression | t.ArrowFunctionExpression | t.FunctionDeclaration
2979
+ >
2980
): InstructionValue {
2981
const exprNode = expr.node;
2982
const exprLoc = exprNode.loc ?? GeneratedSource;
@@ -3016,7 +3000,10 @@ function lowerFunctionExpression(
3000
function lowerFunction(
3001
builder: HIRBuilder,
3002
expr: NodePath<
3019
- t.FunctionExpression | t.ArrowFunctionExpression | t.ObjectMethod
3003
+ | t.FunctionExpression
3004
+ | t.ArrowFunctionExpression
3005
+ | t.FunctionDeclaration
3006
+ | t.ObjectMethod
3007
>
3008
): LoweredFunction | null {
3009
const componentScope: Scope = builder.parentFunction.scope;
@@ -3638,7 +3625,10 @@ function captureScopes({ from, to }: { from: Scope; to: Scope }): Set<Scope> {
3625
function gatherCapturedDeps(
3626
builder: HIRBuilder,
3627
fn: NodePath<
3641
- t.FunctionExpression | t.ArrowFunctionExpression | t.ObjectMethod
3628
+ | t.FunctionExpression
3629
+ | t.ArrowFunctionExpression
3630
+ | t.FunctionDeclaration
3631
+ | t.ObjectMethod
3632
>,
3633
componentScope: Scope
3634
): { identifiers: t.Identifier[]; refs: Place[] } {
compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts
+4
-1
@@ -862,7 +862,10 @@ export type FunctionExpression = {
862
kind: "FunctionExpression";
863
name: string | null;
864
loweredFunc: LoweredFunction;
865
- expr: t.ArrowFunctionExpression | t.FunctionExpression;
865
+ expr:
866
+ | t.ArrowFunctionExpression
867
+ | t.FunctionExpression
868
+ | t.FunctionDeclaration;
869
loc: SourceLocation;
870
};
871
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.hoisted-function-declaration.expect.md
+1
-1
@@ -17,7 +17,7 @@ function component(a) {
17
## Error
18
19
```
20
-[ReactForget] Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used. Identifier x$5 is undefined
20
+[ReactForget] Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used. Identifier x$5 is undefined (4:6)
21
```
22
23
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/hoisting-computed-member-expression.expect.md
+1
@@ -34,6 +34,7 @@ function hoisting() {
34
onClick = function onClick(x) {
35
return x + bar.baz;
36
};
37
+
38
onClick2 = function onClick2(x_0) {
39
return x_0 + bar[baz];
40
};