Enable compilation of FunctionExpressions
Thanks to the previous diff we can trivially support components or hooks defined as a FunctionExpression.
Joe Savona committed
Aug 29, 2023 at 22:09 UTC
ddc9f8030e179f01959e465261c0fd5acfe0eb4e
9 files changed
+94
-6
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+13
@@ -265,6 +265,19 @@ export function compileProgram(
265
}
266
},
267
268
+ FunctionExpression(
269
+ fn: NodePath<t.FunctionExpression>,
270
+ pass: CompilerPass
271
+ ): void {
272
+ if (!shouldVisitNode(fn, pass)) {
273
+ return;
274
+ }
275
+
276
+ if (compileAndInsertNewFunctionDeclaration(fn, pass) === true) {
277
+ hasForgetMutatedOriginalSource = true;
278
+ }
279
+ },
280
+
281
ArrowFunctionExpression(
282
fn: NodePath<t.ArrowFunctionExpression>,
283
pass: CompilerPass
compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+2
@@ -83,6 +83,8 @@ export function lower(
83
let id: string | null = null;
84
if (func.isFunctionDeclaration() && func.get("id").node != null) {
85
id = (func.get("id") as NodePath<t.Identifier>).node.name;
86
+ } else if (func.isFunctionExpression() && func.get("id").node != null) {
87
+ id = (func.get("id") as NodePath<t.Identifier>).node.name;
88
}
89
const params: Array<Place> = [];
90
func.get("params").forEach((param) => {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-function-expression-component.expect.md
new
+31
@@ -0,0 +1,31 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @compilationMode(infer)
6
+
7
+const Component = function ComponentName(props) {
8
+ return <Foo />;
9
+};
10
+
11
+```
12
+
13
+## Code
14
+
15
+```javascript
16
+import { unstable_useMemoCache as useMemoCache } from "react"; // @compilationMode(infer)
17
+
18
+const Component = function ComponentName(props) {
19
+ const $ = useMemoCache(1);
20
+ let t0;
21
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
22
+ t0 = <Foo />;
23
+ $[0] = t0;
24
+ } else {
25
+ t0 = $[0];
26
+ }
27
+ return t0;
28
+};
29
+
30
+```
31
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-function-expression-component.js
new
+5
@@ -0,0 +1,5 @@
1
+// @compilationMode(infer)
2
+
3
+const Component = function ComponentName(props) {
4
+ return <Foo />;
5
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-9a47e97b5d13.expect.md
+14
-2
@@ -14,11 +14,23 @@ const FancyButton = React.forwardRef(function (props, ref) {
14
## Code
15
16
```javascript
17
-// Valid because hooks can be used in anonymous function arguments to
17
+import { unstable_useMemoCache as useMemoCache } from "react"; // Valid because hooks can be used in anonymous function arguments to
18
// forwardRef.
19
const FancyButton = React.forwardRef(function (props, ref) {
20
+ const $ = useMemoCache(3);
21
useHook();
21
- return <button {...props} ref={ref} />;
22
+ const c_0 = $[0] !== props;
23
+ const c_1 = $[1] !== ref;
24
+ let t0;
25
+ if (c_0 || c_1) {
26
+ t0 = <button {...props} ref={ref} />;
27
+ $[0] = props;
28
+ $[1] = ref;
29
+ $[2] = t0;
30
+ } else {
31
+ t0 = $[2];
32
+ }
33
+ return t0;
34
});
35
36
```
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-e66a744cffbe.expect.md
+14
-2
@@ -14,11 +14,23 @@ const FancyButton = forwardRef(function (props, ref) {
14
## Code
15
16
```javascript
17
-// Valid because hooks can be used in anonymous function arguments to
17
+import { unstable_useMemoCache as useMemoCache } from "react"; // Valid because hooks can be used in anonymous function arguments to
18
// forwardRef.
19
const FancyButton = forwardRef(function (props, ref) {
20
+ const $ = useMemoCache(3);
21
useHook();
21
- return <button {...props} ref={ref} />;
22
+ const c_0 = $[0] !== props;
23
+ const c_1 = $[1] !== ref;
24
+ let t0;
25
+ if (c_0 || c_1) {
26
+ t0 = <button {...props} ref={ref} />;
27
+ $[0] = props;
28
+ $[1] = ref;
29
+ $[2] = t0;
30
+ } else {
31
+ t0 = $[2];
32
+ }
33
+ return t0;
34
});
35
36
```
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-eacfcaa6ef89.expect.md
+12
-2
@@ -14,11 +14,21 @@ const MemoizedFunction = memo(function (props) {
14
## Code
15
16
```javascript
17
-// Valid because hooks can be used in anonymous function arguments to
17
+import { unstable_useMemoCache as useMemoCache } from "react"; // Valid because hooks can be used in anonymous function arguments to
18
// memo.
19
const MemoizedFunction = memo(function (props) {
20
+ const $ = useMemoCache(2);
21
useHook();
21
- return <button {...props} />;
22
+ const c_0 = $[0] !== props;
23
+ let t0;
24
+ if (c_0) {
25
+ t0 = <button {...props} />;
26
+ $[0] = props;
27
+ $[1] = t0;
28
+ } else {
29
+ t0 = $[1];
30
+ }
31
+ return t0;
32
});
33
34
```
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-fe6042f7628b.expect.md
+2
@@ -2,6 +2,7 @@
2
## Input
3
4
```javascript
5
+// @compilationMode(infer)
6
// This is valid because "use"-prefixed functions called in
7
// unnamed function arguments are not assumed to be hooks.
8
unknownFunction(function (foo, bar) {
@@ -15,6 +16,7 @@ unknownFunction(function (foo, bar) {
16
## Code
17
18
```javascript
19
+// @compilationMode(infer)
20
// This is valid because "use"-prefixed functions called in
21
// unnamed function arguments are not assumed to be hooks.
22
unknownFunction(function (foo, bar) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-fe6042f7628b.js
+1
@@ -1,3 +1,4 @@
1
+// @compilationMode(infer)
2
// This is valid because "use"-prefixed functions called in
3
// unnamed function arguments are not assumed to be hooks.
4
unknownFunction(function (foo, bar) {