Fixture for only early return without decls/deps/reassigns
Joe Savona committed
Dec 20, 2023 at 13:52 UTC
a753a326ad77145e4d8eb6a44e40758d82869669
2 files changed
+180
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md
new
+135
@@ -0,0 +1,135 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @enableEarlyReturnInReactiveScopes
6
+import { makeArray } from "shared-runtime";
7
+
8
+/**
9
+ * This fixture tests what happens when a reactive has no declarations (other than an early return),
10
+ * no reassignments, and no dependencies. In this case the only thing we can use to decide if we
11
+ * should take the if or else branch is the early return declaration. But if that uses the same
12
+ * sentinel as the memo cache sentinel, then if the previous execution did not early return it will
13
+ * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping
14
+ * to the else branch.
15
+ *
16
+ * We have to use a distinct sentinel for the early return value.
17
+ *
18
+ * Here the fixture will always take the "else" branch and never early return, and we should see that
19
+ * "recreate x" is only logged once, the first time we execute.
20
+ */
21
+let ENABLE_FEATURE = false;
22
+
23
+function Component(props) {
24
+ let x = [];
25
+ console.log("recreate x");
26
+ if (ENABLE_FEATURE) {
27
+ x.push(42);
28
+ console.log("early return");
29
+ return x;
30
+ } else {
31
+ console.log("fallthrough");
32
+ }
33
+ return makeArray(props.a);
34
+}
35
+
36
+export const FIXTURE_ENTRYPOINT = {
37
+ fn: Component,
38
+ params: [],
39
+ sequentialRenders: [
40
+ { a: 42 },
41
+ { a: 42 },
42
+ { a: 3.14 },
43
+ { a: 3.14 },
44
+ { a: 42 },
45
+ { a: 3.14 },
46
+ { a: 42 },
47
+ { a: 3.14 },
48
+ ],
49
+};
50
+
51
+```
52
+
53
+## Code
54
+
55
+```javascript
56
+import { unstable_useMemoCache as useMemoCache } from "react"; // @enableEarlyReturnInReactiveScopes
57
+import { makeArray } from "shared-runtime";
58
+
59
+/**
60
+ * This fixture tests what happens when a reactive has no declarations (other than an early return),
61
+ * no reassignments, and no dependencies. In this case the only thing we can use to decide if we
62
+ * should take the if or else branch is the early return declaration. But if that uses the same
63
+ * sentinel as the memo cache sentinel, then if the previous execution did not early return it will
64
+ * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping
65
+ * to the else branch.
66
+ *
67
+ * We have to use a distinct sentinel for the early return value.
68
+ *
69
+ * Here the fixture will always take the "else" branch and never early return, and we should see that
70
+ * "recreate x" is only logged once, the first time we execute.
71
+ */
72
+let ENABLE_FEATURE = false;
73
+
74
+function Component(props) {
75
+ const $ = useMemoCache(3);
76
+ let t53;
77
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
78
+ t53 = Symbol.for("react.memo_cache_sentinel");
79
+ bb8: {
80
+ const x = [];
81
+ console.log("recreate x");
82
+ if (ENABLE_FEATURE) {
83
+ x.push(42);
84
+ console.log("early return");
85
+ t53 = x;
86
+ break bb8;
87
+ }
88
+ }
89
+ $[0] = t53;
90
+ } else {
91
+ t53 = $[0];
92
+ }
93
+ if (t53 !== Symbol.for("react.memo_cache_sentinel")) {
94
+ return t53;
95
+ }
96
+
97
+ console.log("fallthrough");
98
+ let t0;
99
+ if ($[1] !== props.a) {
100
+ t0 = makeArray(props.a);
101
+ $[1] = props.a;
102
+ $[2] = t0;
103
+ } else {
104
+ t0 = $[2];
105
+ }
106
+ return t0;
107
+}
108
+
109
+export const FIXTURE_ENTRYPOINT = {
110
+ fn: Component,
111
+ params: [],
112
+ sequentialRenders: [
113
+ { a: 42 },
114
+ { a: 42 },
115
+ { a: 3.14 },
116
+ { a: 3.14 },
117
+ { a: 42 },
118
+ { a: 3.14 },
119
+ { a: 42 },
120
+ { a: 3.14 },
121
+ ],
122
+};
123
+
124
+```
125
+
126
+### Eval output
127
+(kind: ok) [42]
128
+[42]
129
+[3.14]
130
+[3.14]
131
+[42]
132
+[3.14]
133
+[42]
134
+[3.14]
135
+logs: ['recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough','recreate x','fallthrough']
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.js
new
+45
@@ -0,0 +1,45 @@
1
+// @enableEarlyReturnInReactiveScopes
2
+import { makeArray } from "shared-runtime";
3
+
4
+/**
5
+ * This fixture tests what happens when a reactive has no declarations (other than an early return),
6
+ * no reassignments, and no dependencies. In this case the only thing we can use to decide if we
7
+ * should take the if or else branch is the early return declaration. But if that uses the same
8
+ * sentinel as the memo cache sentinel, then if the previous execution did not early return it will
9
+ * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping
10
+ * to the else branch.
11
+ *
12
+ * We have to use a distinct sentinel for the early return value.
13
+ *
14
+ * Here the fixture will always take the "else" branch and never early return, and we should see that
15
+ * "recreate x" is only logged once, the first time we execute.
16
+ */
17
+let ENABLE_FEATURE = false;
18
+
19
+function Component(props) {
20
+ let x = [];
21
+ console.log("recreate x");
22
+ if (ENABLE_FEATURE) {
23
+ x.push(42);
24
+ console.log("early return");
25
+ return x;
26
+ } else {
27
+ console.log("fallthrough");
28
+ }
29
+ return makeArray(props.a);
30
+}
31
+
32
+export const FIXTURE_ENTRYPOINT = {
33
+ fn: Component,
34
+ params: [],
35
+ sequentialRenders: [
36
+ { a: 42 },
37
+ { a: 42 },
38
+ { a: 3.14 },
39
+ { a: 3.14 },
40
+ { a: 42 },
41
+ { a: 3.14 },
42
+ { a: 42 },
43
+ { a: 3.14 },
44
+ ],
45
+};