Fix calculation of nested function dependencies
We were incorrectly calculating the dependencies of nested lambdas, because the "component" scope was incorrectly set to the next closest parent rather than outermost React function (component/hook) being compiled.
Joe Savona committed
Jun 14, 2023 at 14:04 UTC
a21660de006416018d1fc799be92540417fcb8bb
3 files changed
+79
-1
compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+1
-1
@@ -2344,7 +2344,7 @@ function lowerFunctionExpression(
2344
if (expr.isFunctionExpression()) {
2345
name = expr.get("id")?.node?.name ?? null;
2346
}
2347
- const componentScope: Scope = expr.scope.parent.getFunctionParent()!;
2347
+ const componentScope: Scope = builder.parentFunction.scope;
2348
const captured = gatherCapturedDeps(builder, expr, componentScope);
2349
2350
// TODO(gsn): In the future, we could only pass in the context identifiers
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro.expect.md
new
+64
@@ -0,0 +1,64 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Component(props) {
6
+ const item = props.item;
7
+ const thumbnails = [];
8
+ const baseVideos = getBaseVideos(item);
9
+ useMemo(() => {
10
+ baseVideos.forEach((video) => {
11
+ const baseVideo = video.hasBaseVideo;
12
+ if (Boolean(baseVideo)) {
13
+ thumbnails.push({ extraVideo: true });
14
+ }
15
+ });
16
+ });
17
+ return <FlatList baseVideos={baseVideos} items={thumbnails} />;
18
+}
19
+
20
+```
21
+
22
+## Code
23
+
24
+```javascript
25
+import { unstable_useMemoCache as useMemoCache } from "react";
26
+function Component(props) {
27
+ const $ = useMemoCache(6);
28
+ const item = props.item;
29
+ const c_0 = $[0] !== item;
30
+ let baseVideos;
31
+ let thumbnails;
32
+ if (c_0) {
33
+ thumbnails = [];
34
+ baseVideos = getBaseVideos(item);
35
+
36
+ baseVideos.forEach((video) => {
37
+ const baseVideo = video.hasBaseVideo;
38
+ if (Boolean(baseVideo)) {
39
+ thumbnails.push({ extraVideo: true });
40
+ }
41
+ });
42
+ $[0] = item;
43
+ $[1] = baseVideos;
44
+ $[2] = thumbnails;
45
+ } else {
46
+ baseVideos = $[1];
47
+ thumbnails = $[2];
48
+ }
49
+ const c_3 = $[3] !== baseVideos;
50
+ const c_4 = $[4] !== thumbnails;
51
+ let t0;
52
+ if (c_3 || c_4) {
53
+ t0 = <FlatList baseVideos={baseVideos} items={thumbnails} />;
54
+ $[3] = baseVideos;
55
+ $[4] = thumbnails;
56
+ $[5] = t0;
57
+ } else {
58
+ t0 = $[5];
59
+ }
60
+ return t0;
61
+}
62
+
63
+```
64
+
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro.js
new
+14
@@ -0,0 +1,14 @@
1
+function Component(props) {
2
+ const item = props.item;
3
+ const thumbnails = [];
4
+ const baseVideos = getBaseVideos(item);
5
+ useMemo(() => {
6
+ baseVideos.forEach((video) => {
7
+ const baseVideo = video.hasBaseVideo;
8
+ if (Boolean(baseVideo)) {
9
+ thumbnails.push({ extraVideo: true });
10
+ }
11
+ });
12
+ });
13
+ return <FlatList baseVideos={baseVideos} items={thumbnails} />;
14
+}