@samitouri / QOS-React-2 / commits / 8176ebb546

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