@samitouri / QOS-React-1 / commits / 428c47581e

Generalize InlineUseMemo to inline IIFEs

This PR completes the refactor. We now do the following sequence: * ValidateUseMemo. This is a new pass that extracts just the validation logic from the existing InlineUseMemo. This was always being run before, so this pass also always runs. * DropManualMemoization. As before, this converts useMemo calls into an IIFE (immediately invoked function expression). * InlineImmediatelyInvokedFunctionExpressions (prev InlineUseMemo). This pass now inlines _all_ IIFEs, including both useMemo calls that were dropped as well as IIFEs that the user wrote. The motivation for this change is that some codebases use IIFEs as a workaround for lack of if expressions, but we're unable to optimize within function expressions. This is the reason we originally added inlining for useMemo, but given that IIFEs are common it makes sense to generalize the inlining. ## Test Plan * Manually checked changes in output * Synced internally and tested on profile page, no issues observed. Also spot-checked some of the changes in ouput and it looks as expected.

Joe Savona committed Oct 9, 2023 at 15:56 UTC 428c47581e7d175c8f54a7c21600e613460a89ff
73 files changed +1457 -228
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Pipeline.ts
+6 -3
@@ -72,6 +72,7 @@ import {
72 validateNoRefAccessInRender,
73 validateNoSetStateInRender,
74 validateUnconditionalHooks,
75 + validateUseMemo,
76 } from "../Validation";
77
78 export type CompilerPipelineValue =
@@ -133,6 +134,8 @@ function* runWithEnvironment(
134 inferTypes(hir);
135 yield log({ kind: "hir", name: "InferTypes", value: hir });
136
137 + validateUseMemo(hir);
138 +
139 if (env.config.validateHooksUsage) {
140 validateHooksUsage(hir);
141 const conditionalHooksResult = validateUnconditionalHooks(hir).unwrap();
@@ -143,12 +146,12 @@ function* runWithEnvironment(
146 });
147 }
148
146 - inlineUseMemo(hir);
147 - yield log({ kind: "hir", name: "InlineUseMemo", value: hir });
148 -
149 dropManualMemoization(hir);
150 yield log({ kind: "hir", name: "DropManualMemoization", value: hir });
151
152 + inlineUseMemo(hir);
153 + yield log({ kind: "hir", name: "InlineUseMemo", value: hir });
154 +
155 analyseFunctions(hir);
156 yield log({ kind: "hir", name: "AnalyseFunctions", value: hir });
157
compiler/packages/babel-plugin-react-forget/src/Inference/InlineImmediatelyInvokedFunctionExpressions.ts renamed
+75 -72
@@ -5,7 +5,6 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 -import { CompilerError } from "../CompilerError";
8 import {
9 BasicBlock,
10 BlockId,
@@ -20,56 +19,70 @@ import {
19 InstructionKind,
20 LabelTerminal,
21 Place,
23 - getHookKind,
22 makeInstructionId,
23 makeType,
24 reversePostorderBlocks,
25 } from "../HIR";
26 import { markInstructionIds, markPredecessors } from "../HIR/HIRBuilder";
27 +import { eachInstructionValueOperand } from "../HIR/visitors";
28 import { retainWhere } from "../Utils/utils";
29
30 /**
32 - * Rewrites `useMemo()` calls, rewriting so that the lambda body becomes part of the
33 - * outer block's instructions.
31 + * Inlines immediately invoked function expressions (IIFEs) to allow more fine-grained memoization
32 + * of the values they produce.
33 *
34 * Example:
35 *
37 - * ```javascript
38 - * // Before
39 - * const x = useMemo(() => foo(y, z), [y, z])
40 - *
41 - * // After
42 - * const x = foo(y, z);
36 * ```
37 + * const x = (() => {
38 + * const x = [];
39 + * x.push(foo());
40 + * return x;
41 + * })();
42 + *
43 + * =>
44 *
45 - * The main challenge is dealing with the possibility of complex control flow within
46 - * the lambda body. The approach is roughly:
47 - * - split the block with the useMemo call in two:
48 - * - the first block is everything up to the memo call plus the lambda body
49 - * - the second block is everything after the memo call
50 - * - use the temporary from the useMemo call result value as the place to store
51 - * the useMemo result
52 - * - for every return terminal in the lambda body:
53 - * - add a StoreLocal to the temporary, assigning the return value
54 - * - replace the terminal w a goto to the second block
45 + * bb0:
46 + * // placeholder for the result, all return statements will assign here
47 + * let t0;
48 + * // Label allows using a goto (break) to exit out of the body
49 + * Label block=bb1 fallthrough=bb2
50 + * bb1:
51 + * // code within the function expression
52 + * const x0 = [];
53 + * x0.push(foo());
54 + * // return is replaced by assignment to the result variable...
55 + * t0 = x0;
56 + * // ...and a goto to the code after the function expression invocation
57 + * Goto bb2
58 + * bb2:
59 + * // code after the IIFE call
60 + * const x = t0;
61 + * ```
62 *
56 - * NOTE: *this pass must be run prior to EnterSSA*. Prior to entering SSA form identifiers
57 - * in the top-level function and any function expressions will have consistent
58 - * correlation between `Identifier` instances and IdentifierIds. After entering SSA
59 - * form we drop this correspondence. It's much easier to write this inlining pass
60 - * without having to worry about SSA form.
63 + * The implementation relies on HIR's ability to support labeled blocks:
64 + * - We terminate the basic block just prior to the CallExpression of the IIFE
65 + * with a LabelTerminal whose fallback is the code following the CallExpression.
66 + * Just prior to the terminal we also create a named temporary variable which
67 + * will hold the result.
68 + * - We then inline the contents of the function "in between" (conceptually) those
69 + * two blocks.
70 + * - All return statements in the original function expression are replaced with a
71 + * StoreLocal to the temporary we allocated before plus a Goto to the fallthrough
72 + * block (code following the CallExpression).
73 */
62 -export function inlineUseMemo(fn: HIRFunction): void {
63 - // Track all function expressions in case they appear as the argument to a useMemo
74 +export function inlineImmediatelyInvokedFunctionExpressions(
75 + fn: HIRFunction
76 +): void {
77 + // Track all function expressions that are assigned to a temporary
78 const functions = new Map<IdentifierId, FunctionExpression>();
65 - // Identifiers (lvalues) for known useMemo functions, so that we can prune them
66 - // at the end of the pass
67 - const useMemoFunctions = new Set<IdentifierId>();
79 + // Functions that are inlined
80 + const inlinedFunctions = new Set<IdentifierId>();
81
69 - // Iterate the *existing* blocks from the outer component to find useMemo calls
82 + // Iterate the *existing* blocks from the outer component to find IIFEs
83 // and inline them. During iteration we will modify `fn` (by inlining the CFG
71 - // of useMemo callbacks) so we explicitly copy references to just the original
72 - // function's blocks first. As blocks are split to make room for useMemo calls,
84 + // of IIFEs) so we explicitly copy references to just the original
85 + // function's blocks first. As blocks are split to make room for IIFE calls,
86 // the split portions of the blocks will be added to this queue.
87 const queue = Array.from(fn.body.blocks.values());
88 queue: for (const block of queue) {
@@ -77,51 +90,35 @@ export function inlineUseMemo(fn: HIRFunction): void {
90 const instr = block.instructions[ii]!;
91 switch (instr.value.kind) {
92 case "FunctionExpression": {
80 - functions.set(instr.lvalue.identifier.id, instr.value);
93 + if (instr.lvalue.identifier.name === null) {
94 + functions.set(instr.lvalue.identifier.id, instr.value);
95 + }
96 break;
97 }
83 - case "MethodCall":
98 case "CallExpression": {
85 - const hookKind =
86 - instr.value.kind === "CallExpression"
87 - ? getHookKind(fn.env, instr.value.callee.identifier)
88 - : getHookKind(fn.env, instr.value.property.identifier);
89 - if (hookKind !== "useMemo") {
90 - continue;
91 - }
92 - const [lambda] = instr.value.args;
93 - if (lambda.kind === "Spread") {
99 + if (instr.value.args.length !== 0) {
100 + // We don't support inlining when there are arguments
101 continue;
102 }
96 - const body = functions.get(lambda.identifier.id);
103 + const body = functions.get(instr.value.callee.identifier.id);
104 if (body === undefined) {
98 - // Allow passing a named function to useMemo, eg `useMemo(someImportedFunction, [])`
105 + // Not invoking a local function expression, can't inline
106 continue;
107 }
108
102 - if (body.loweredFunc.func.params.length > 0) {
103 - CompilerError.invalidReact({
104 - reason: "useMemo callbacks may not accept any arguments",
105 - description: null,
106 - loc: body.loc,
107 - suggestions: null,
108 - });
109 - }
110 -
111 - if (body.loweredFunc.func.async || body.loweredFunc.func.generator) {
112 - CompilerError.invalidReact({
113 - reason:
114 - "useMemo callbacks may not be async or generator functions",
115 - description: null,
116 - loc: body.loc,
117 - suggestions: null,
118 - });
109 + if (
110 + body.loweredFunc.func.params.length > 0 ||
111 + body.loweredFunc.func.async ||
112 + body.loweredFunc.func.generator
113 + ) {
114 + // Can't inline functions with params, or async/generator functions
115 + continue;
116 }
117
121 - // We know this function is used for useMemo and can prune it later
122 - useMemoFunctions.add(lambda.identifier.id);
118 + // We know this function is used for an IIFE and can prune it later
119 + inlinedFunctions.add(instr.value.callee.identifier.id);
120
124 - // Create a new block which will contain code following the useMemo call
121 + // Create a new block which will contain code following the IIFE call
122 const continuationBlockId = fn.env.nextBlockId;
123 const continuationBlock: BasicBlock = {
124 id: continuationBlockId,
@@ -134,7 +131,7 @@ export function inlineUseMemo(fn: HIRFunction): void {
131 fn.body.blocks.set(continuationBlockId, continuationBlock);
132
133 // Trim the original block to contain instructions up to (but not including)
137 - // the useMemo
134 + // the IIFE
135 block.instructions.length = ii;
136
137 // To account for complex control flow within the lambda, we treat the lambda
@@ -149,10 +146,10 @@ export function inlineUseMemo(fn: HIRFunction): void {
146 };
147 block.terminal = newTerminal;
148
152 - // We store the result in the useMemo temporary
149 + // We store the result in the IIFE temporary
150 const result = instr.lvalue;
151
155 - // Declare the useMemo temporary
152 + // Declare the IIFE temporary
153 declareTemporary(fn.env, block, result);
154
155 // Promote the temporary with a name as we require this to persist
@@ -167,20 +164,26 @@ export function inlineUseMemo(fn: HIRFunction): void {
164 }
165
166 // Ensure we visit the continuation block, since there may have been
170 - // sequential useMemos that need to be visited.
167 + // sequential IIFEs that need to be visited.
168 queue.push(continuationBlock);
169 continue queue;
170 }
171 + default: {
172 + for (const place of eachInstructionValueOperand(instr.value)) {
173 + // Any other use of a function expression means it isn't an IIFE
174 + functions.delete(place.identifier.id);
175 + }
176 + }
177 }
178 }
179 }
180
178 - if (useMemoFunctions.size !== 0) {
181 + if (inlinedFunctions.size !== 0) {
182 // Remove instructions that define lambdas which we inlined
183 for (const [, block] of fn.body.blocks) {
184 retainWhere(
185 block.instructions,
183 - (instr) => !useMemoFunctions.has(instr.lvalue.identifier.id)
186 + (instr) => !inlinedFunctions.has(instr.lvalue.identifier.id)
187 );
188 }
189
compiler/packages/babel-plugin-react-forget/src/Inference/index.ts
+1 -1
@@ -9,4 +9,4 @@ export { default as analyseFunctions } from "./AnalyseFunctions";
9 export { dropManualMemoization } from "./DropManualMemoization";
10 export { inferMutableRanges } from "./InferMutableRanges";
11 export { default as inferReferenceEffects } from "./InferReferenceEffects";
12 -export { inlineUseMemo } from "./InlineUseMemo";
12 +export { inlineImmediatelyInvokedFunctionExpressions as inlineUseMemo } from "./InlineImmediatelyInvokedFunctionExpressions";
compiler/packages/babel-plugin-react-forget/src/Validation/ValidateUseMemo.ts new
+72
@@ -0,0 +1,72 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import { CompilerError } from "..";
9 +import {
10 + FunctionExpression,
11 + HIRFunction,
12 + IdentifierId,
13 + getHookKind,
14 +} from "../HIR";
15 +
16 +export function validateUseMemo(fn: HIRFunction): void {
17 + const functions = new Map<IdentifierId, FunctionExpression>();
18 + for (const [, block] of fn.body.blocks) {
19 + for (const { lvalue, value } of block.instructions) {
20 + switch (value.kind) {
21 + case "FunctionExpression": {
22 + functions.set(lvalue.identifier.id, value);
23 + break;
24 + }
25 + case "MethodCall":
26 + case "CallExpression": {
27 + // Is the function being called useMemo, with at least 1 argument?
28 + const callee =
29 + value.kind === "CallExpression"
30 + ? value.callee.identifier
31 + : value.property.identifier;
32 + const hookKind = getHookKind(fn.env, callee);
33 + if (hookKind !== "useMemo" || value.args.length === 0) {
34 + continue;
35 + }
36 +
37 + // If yes get the first argument and if it refers to a locally defined function
38 + // expression, validate the function
39 + const [arg] = value.args;
40 + if (arg.kind !== "Identifier") {
41 + continue;
42 + }
43 + const body = functions.get(arg.identifier.id);
44 + if (body === undefined) {
45 + continue;
46 + }
47 +
48 + if (body.loweredFunc.func.params.length > 0) {
49 + CompilerError.invalidReact({
50 + reason: "useMemo callbacks may not accept any arguments",
51 + description: null,
52 + loc: body.loc,
53 + suggestions: null,
54 + });
55 + }
56 +
57 + if (body.loweredFunc.func.async || body.loweredFunc.func.generator) {
58 + CompilerError.invalidReact({
59 + reason:
60 + "useMemo callbacks may not be async or generator functions",
61 + description: null,
62 + loc: body.loc,
63 + suggestions: null,
64 + });
65 + }
66 +
67 + break;
68 + }
69 + }
70 + }
71 + }
72 +}
compiler/packages/babel-plugin-react-forget/src/Validation/index.ts
+1
@@ -10,3 +10,4 @@ export { validateHooksUsage } from "./ValidateHooksUsage";
10 export { validateNoRefAccessInRender } from "./ValidateNoRefAccesInRender";
11 export { validateNoSetStateInRender } from "./ValidateNoSetStateInRender";
12 export { validateUnconditionalHooks } from "./ValidateUnconditionalHooks";
13 +export { validateUseMemo } from "./ValidateUseMemo";
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias-iife.expect.md new
+55
@@ -0,0 +1,55 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function component(a) {
6 + let x = { a };
7 + (function () {
8 + let q = x;
9 + (function () {
10 + q.b = 1;
11 + })();
12 + })();
13 +
14 + return x;
15 +}
16 +
17 +export const FIXTURE_ENTRYPOINT = {
18 + fn: component,
19 + params: ["TodoAdd"],
20 + isComponent: "TodoAdd",
21 +};
22 +
23 +```
24 +
25 +## Code
26 +
27 +```javascript
28 +import { unstable_useMemoCache as useMemoCache } from "react";
29 +function component(a) {
30 + const $ = useMemoCache(2);
31 + const c_0 = $[0] !== a;
32 + let x;
33 + if (c_0) {
34 + x = { a };
35 +
36 + const q = x;
37 + (function () {
38 + q.b = 1;
39 + })();
40 + $[0] = a;
41 + $[1] = x;
42 + } else {
43 + x = $[1];
44 + }
45 + return x;
46 +}
47 +
48 +export const FIXTURE_ENTRYPOINT = {
49 + fn: component,
50 + params: ["TodoAdd"],
51 + isComponent: "TodoAdd",
52 +};
53 +
54 +```
55 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias-iife.js new
+17
@@ -0,0 +1,17 @@
1 +function component(a) {
2 + let x = { a };
3 + (function () {
4 + let q = x;
5 + (function () {
6 + q.b = 1;
7 + })();
8 + })();
9 +
10 + return x;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: component,
15 + params: ["TodoAdd"],
16 + isComponent: "TodoAdd",
17 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias.expect.md
+14 -8
@@ -4,12 +4,14 @@
4 ```javascript
5 function component(a) {
6 let x = { a };
7 - (function () {
7 + const f0 = function () {
8 let q = x;
9 - (function () {
9 + const f1 = function () {
10 q.b = 1;
11 - })();
12 - })();
11 + };
12 + f1();
13 + };
14 + f0();
15
16 return x;
17 }
@@ -32,12 +34,16 @@ function component(a) {
34 let x;
35 if (c_0) {
36 x = { a };
35 - (function () {
37 + const f0 = function () {
38 const q = x;
37 - (function () {
39 + const f1 = function () {
40 q.b = 1;
39 - })();
40 - })();
41 + };
42 +
43 + f1();
44 + };
45 +
46 + f0();
47 $[0] = a;
48 $[1] = x;
49 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias.js
+6 -4
@@ -1,11 +1,13 @@
1 function component(a) {
2 let x = { a };
3 - (function () {
3 + const f0 = function () {
4 let q = x;
5 - (function () {
5 + const f1 = function () {
6 q.b = 1;
7 - })();
8 - })();
7 + };
8 + f1();
9 + };
10 + f0();
11
12 return x;
13 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture_mutate-across-fns-iife.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function component(a) {
6 + let z = { a };
7 + (function () {
8 + (function () {
9 + z.b = 1;
10 + })();
11 + })();
12 + return z;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: component,
17 + params: ["TodoAdd"],
18 + isComponent: "TodoAdd",
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { unstable_useMemoCache as useMemoCache } from "react";
27 +function component(a) {
28 + const $ = useMemoCache(2);
29 + const c_0 = $[0] !== a;
30 + let z;
31 + if (c_0) {
32 + z = { a };
33 +
34 + (function () {
35 + z.b = 1;
36 + })();
37 + $[0] = a;
38 + $[1] = z;
39 + } else {
40 + z = $[1];
41 + }
42 + return z;
43 +}
44 +
45 +export const FIXTURE_ENTRYPOINT = {
46 + fn: component,
47 + params: ["TodoAdd"],
48 + isComponent: "TodoAdd",
49 +};
50 +
51 +```
52 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture_mutate-across-fns-iife.js new
+15
@@ -0,0 +1,15 @@
1 +function component(a) {
2 + let z = { a };
3 + (function () {
4 + (function () {
5 + z.b = 1;
6 + })();
7 + })();
8 + return z;
9 +}
10 +
11 +export const FIXTURE_ENTRYPOINT = {
12 + fn: component,
13 + params: ["TodoAdd"],
14 + isComponent: "TodoAdd",
15 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture_mutate-across-fns.expect.md
+14 -8
@@ -4,11 +4,13 @@
4 ```javascript
5 function component(a) {
6 let z = { a };
7 - (function () {
8 - (function () {
7 + const f0 = function () {
8 + const f1 = function () {
9 z.b = 1;
10 - })();
11 - })();
10 + };
11 + f1();
12 + };
13 + f0();
14 return z;
15 }
16
@@ -30,11 +32,15 @@ function component(a) {
32 let z;
33 if (c_0) {
34 z = { a };
33 - (function () {
34 - (function () {
35 + const f0 = function () {
36 + const f1 = function () {
37 z.b = 1;
36 - })();
37 - })();
38 + };
39 +
40 + f1();
41 + };
42 +
43 + f0();
44 $[0] = a;
45 $[1] = z;
46 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capture_mutate-across-fns.js
+6 -4
@@ -1,10 +1,12 @@
1 function component(a) {
2 let z = { a };
3 - (function () {
4 - (function () {
3 + const f0 = function () {
4 + const f1 = function () {
5 z.b = 1;
6 - })();
7 - })();
6 + };
7 + f1();
8 + };
9 + f0();
10 return z;
11 }
12
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2-iife.expect.md new
+61
@@ -0,0 +1,61 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { mutate } from "shared-runtime";
6 +
7 +function component(foo, bar) {
8 + let x = { foo };
9 + let y = { bar };
10 + (function () {
11 + let a = { y };
12 + let b = x;
13 + a.x = b;
14 + })();
15 + mutate(y);
16 + return x;
17 +}
18 +
19 +export const FIXTURE_ENTRYPOINT = {
20 + fn: component,
21 + params: ["foo", "bar"],
22 +};
23 +
24 +```
25 +
26 +## Code
27 +
28 +```javascript
29 +import { unstable_useMemoCache as useMemoCache } from "react";
30 +import { mutate } from "shared-runtime";
31 +
32 +function component(foo, bar) {
33 + const $ = useMemoCache(3);
34 + const c_0 = $[0] !== foo;
35 + const c_1 = $[1] !== bar;
36 + let x;
37 + if (c_0 || c_1) {
38 + x = { foo };
39 + const y = { bar };
40 +
41 + const a = { y };
42 + const b = x;
43 + a.x = b;
44 +
45 + mutate(y);
46 + $[0] = foo;
47 + $[1] = bar;
48 + $[2] = x;
49 + } else {
50 + x = $[2];
51 + }
52 + return x;
53 +}
54 +
55 +export const FIXTURE_ENTRYPOINT = {
56 + fn: component,
57 + params: ["foo", "bar"],
58 +};
59 +
60 +```
61 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2-iife.js new
+18
@@ -0,0 +1,18 @@
1 +import { mutate } from "shared-runtime";
2 +
3 +function component(foo, bar) {
4 + let x = { foo };
5 + let y = { bar };
6 + (function () {
7 + let a = { y };
8 + let b = x;
9 + a.x = b;
10 + })();
11 + mutate(y);
12 + return x;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: component,
17 + params: ["foo", "bar"],
18 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2.expect.md
+7 -4
@@ -5,11 +5,12 @@
5 function component(foo, bar) {
6 let x = { foo };
7 let y = { bar };
8 - (function () {
8 + const f0 = function () {
9 let a = { y };
10 let b = x;
11 a.x = b;
12 - })();
12 + };
13 + f0();
14 mutate(y);
15 return x;
16 }
@@ -28,11 +29,13 @@ function component(foo, bar) {
29 if (c_0 || c_1) {
30 x = { foo };
31 const y = { bar };
31 - (function () {
32 + const f0 = function () {
33 const a = { y };
34 const b = x;
35 a.x = b;
35 - })();
36 + };
37 +
38 + f0();
39 mutate(y);
40 $[0] = foo;
41 $[1] = bar;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2.js
+3 -2
@@ -1,11 +1,12 @@
1 function component(foo, bar) {
2 let x = { foo };
3 let y = { bar };
4 - (function () {
4 + const f0 = function () {
5 let a = { y };
6 let b = x;
7 a.x = b;
8 - })();
8 + };
9 + f0();
10 mutate(y);
11 return x;
12 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2-iife.expect.md new
+61
@@ -0,0 +1,61 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(foo, bar) {
8 + let x = { foo };
9 + let y = { bar };
10 + (function () {
11 + let a = [y];
12 + let b = x;
13 + a.x = b;
14 + })();
15 + mutate(y);
16 + return x;
17 +}
18 +
19 +export const FIXTURE_ENTRYPOINT = {
20 + fn: component,
21 + params: ["foo", "bar"],
22 +};
23 +
24 +```
25 +
26 +## Code
27 +
28 +```javascript
29 +import { unstable_useMemoCache as useMemoCache } from "react";
30 +const { mutate } = require("shared-runtime");
31 +
32 +function component(foo, bar) {
33 + const $ = useMemoCache(3);
34 + const c_0 = $[0] !== foo;
35 + const c_1 = $[1] !== bar;
36 + let x;
37 + if (c_0 || c_1) {
38 + x = { foo };
39 + const y = { bar };
40 +
41 + const a = [y];
42 + const b = x;
43 + a.x = b;
44 +
45 + mutate(y);
46 + $[0] = foo;
47 + $[1] = bar;
48 + $[2] = x;
49 + } else {
50 + x = $[2];
51 + }
52 + return x;
53 +}
54 +
55 +export const FIXTURE_ENTRYPOINT = {
56 + fn: component,
57 + params: ["foo", "bar"],
58 +};
59 +
60 +```
61 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2-iife.js new
+18
@@ -0,0 +1,18 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(foo, bar) {
4 + let x = { foo };
5 + let y = { bar };
6 + (function () {
7 + let a = [y];
8 + let b = x;
9 + a.x = b;
10 + })();
11 + mutate(y);
12 + return x;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: component,
17 + params: ["foo", "bar"],
18 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2.expect.md
+7 -4
@@ -5,11 +5,12 @@
5 function component(foo, bar) {
6 let x = { foo };
7 let y = { bar };
8 - (function () {
8 + const f0 = function () {
9 let a = [y];
10 let b = x;
11 a.x = b;
12 - })();
12 + };
13 + f0();
14 mutate(y);
15 return x;
16 }
@@ -28,11 +29,13 @@ function component(foo, bar) {
29 if (c_0 || c_1) {
30 x = { foo };
31 const y = { bar };
31 - (function () {
32 + const f0 = function () {
33 const a = [y];
34 const b = x;
35 a.x = b;
35 - })();
36 + };
37 +
38 + f0();
39 mutate(y);
40 $[0] = foo;
41 $[1] = bar;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2.js
+3 -2
@@ -1,11 +1,12 @@
1 function component(foo, bar) {
2 let x = { foo };
3 let y = { bar };
4 - (function () {
4 + const f0 = function () {
5 let a = [y];
6 let b = x;
7 a.x = b;
8 - })();
8 + };
9 + f0();
10 mutate(y);
11 return x;
12 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr-iife.expect.md new
+61
@@ -0,0 +1,61 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(foo, bar) {
8 + let x = { foo };
9 + let y = { bar };
10 + (function () {
11 + let a = [y];
12 + let b = x;
13 + a.x = b;
14 + })();
15 + mutate(y);
16 + return y;
17 +}
18 +
19 +export const FIXTURE_ENTRYPOINT = {
20 + fn: component,
21 + params: ["foo", "bar"],
22 +};
23 +
24 +```
25 +
26 +## Code
27 +
28 +```javascript
29 +import { unstable_useMemoCache as useMemoCache } from "react";
30 +const { mutate } = require("shared-runtime");
31 +
32 +function component(foo, bar) {
33 + const $ = useMemoCache(3);
34 + const c_0 = $[0] !== foo;
35 + const c_1 = $[1] !== bar;
36 + let y;
37 + if (c_0 || c_1) {
38 + const x = { foo };
39 + y = { bar };
40 +
41 + const a = [y];
42 + const b = x;
43 + a.x = b;
44 +
45 + mutate(y);
46 + $[0] = foo;
47 + $[1] = bar;
48 + $[2] = y;
49 + } else {
50 + y = $[2];
51 + }
52 + return y;
53 +}
54 +
55 +export const FIXTURE_ENTRYPOINT = {
56 + fn: component,
57 + params: ["foo", "bar"],
58 +};
59 +
60 +```
61 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr-iife.js new
+18
@@ -0,0 +1,18 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(foo, bar) {
4 + let x = { foo };
5 + let y = { bar };
6 + (function () {
7 + let a = [y];
8 + let b = x;
9 + a.x = b;
10 + })();
11 + mutate(y);
12 + return y;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: component,
17 + params: ["foo", "bar"],
18 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr.expect.md
+7 -4
@@ -5,11 +5,12 @@
5 function component(foo, bar) {
6 let x = { foo };
7 let y = { bar };
8 - (function () {
8 + const f0 = function () {
9 let a = [y];
10 let b = x;
11 a.x = b;
12 - })();
12 + };
13 + f0();
14 mutate(y);
15 return y;
16 }
@@ -28,11 +29,13 @@ function component(foo, bar) {
29 if (c_0 || c_1) {
30 const x = { foo };
31 y = { bar };
31 - (function () {
32 + const f0 = function () {
33 const a = [y];
34 const b = x;
35 a.x = b;
35 - })();
36 + };
37 +
38 + f0();
39 mutate(y);
40 $[0] = foo;
41 $[1] = bar;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr.js
+3 -2
@@ -1,11 +1,12 @@
1 function component(foo, bar) {
2 let x = { foo };
3 let y = { bar };
4 - (function () {
4 + const f0 = function () {
5 let a = [y];
6 let b = x;
7 a.x = b;
8 - })();
8 + };
9 + f0();
10 mutate(y);
11 return y;
12 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-iife.expect.md new
+61
@@ -0,0 +1,61 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(foo, bar) {
8 + let x = { foo };
9 + let y = { bar };
10 + (function () {
11 + let a = { y };
12 + let b = x;
13 + a.x = b;
14 + })();
15 + mutate(y);
16 + return y;
17 +}
18 +
19 +export const FIXTURE_ENTRYPOINT = {
20 + fn: component,
21 + params: ["foo", "bar"],
22 +};
23 +
24 +```
25 +
26 +## Code
27 +
28 +```javascript
29 +import { unstable_useMemoCache as useMemoCache } from "react";
30 +const { mutate } = require("shared-runtime");
31 +
32 +function component(foo, bar) {
33 + const $ = useMemoCache(3);
34 + const c_0 = $[0] !== foo;
35 + const c_1 = $[1] !== bar;
36 + let y;
37 + if (c_0 || c_1) {
38 + const x = { foo };
39 + y = { bar };
40 +
41 + const a = { y };
42 + const b = x;
43 + a.x = b;
44 +
45 + mutate(y);
46 + $[0] = foo;
47 + $[1] = bar;
48 + $[2] = y;
49 + } else {
50 + y = $[2];
51 + }
52 + return y;
53 +}
54 +
55 +export const FIXTURE_ENTRYPOINT = {
56 + fn: component,
57 + params: ["foo", "bar"],
58 +};
59 +
60 +```
61 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-iife.js new
+18
@@ -0,0 +1,18 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(foo, bar) {
4 + let x = { foo };
5 + let y = { bar };
6 + (function () {
7 + let a = { y };
8 + let b = x;
9 + a.x = b;
10 + })();
11 + mutate(y);
12 + return y;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: component,
17 + params: ["foo", "bar"],
18 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate.expect.md
+7 -4
@@ -5,11 +5,12 @@
5 function component(foo, bar) {
6 let x = { foo };
7 let y = { bar };
8 - (function () {
8 + const f0 = function () {
9 let a = { y };
10 let b = x;
11 a.x = b;
12 - })();
12 + };
13 + f0();
14 mutate(y);
15 return y;
16 }
@@ -28,11 +29,13 @@ function component(foo, bar) {
29 if (c_0 || c_1) {
30 const x = { foo };
31 y = { bar };
31 - (function () {
32 + const f0 = function () {
33 const a = { y };
34 const b = x;
35 a.x = b;
35 - })();
36 + };
37 +
38 + f0();
39 mutate(y);
40 $[0] = foo;
41 $[1] = bar;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate.js
+3 -2
@@ -1,11 +1,12 @@
1 function component(foo, bar) {
2 let x = { foo };
3 let y = { bar };
4 - (function () {
4 + const f0 = function () {
5 let a = { y };
6 let b = x;
7 a.x = b;
8 - })();
8 + };
9 + f0();
10 mutate(y);
11 return y;
12 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate-iife.expect.md new
+55
@@ -0,0 +1,55 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(a) {
8 + let x = { a };
9 + let y = {};
10 + (function () {
11 + y["x"] = x;
12 + })();
13 + mutate(y);
14 + return y;
15 +}
16 +
17 +export const FIXTURE_ENTRYPOINT = {
18 + fn: component,
19 + params: ["foo"],
20 +};
21 +
22 +```
23 +
24 +## Code
25 +
26 +```javascript
27 +import { unstable_useMemoCache as useMemoCache } from "react";
28 +const { mutate } = require("shared-runtime");
29 +
30 +function component(a) {
31 + const $ = useMemoCache(2);
32 + const c_0 = $[0] !== a;
33 + let y;
34 + if (c_0) {
35 + const x = { a };
36 + y = {};
37 +
38 + y.x = x;
39 +
40 + mutate(y);
41 + $[0] = a;
42 + $[1] = y;
43 + } else {
44 + y = $[1];
45 + }
46 + return y;
47 +}
48 +
49 +export const FIXTURE_ENTRYPOINT = {
50 + fn: component,
51 + params: ["foo"],
52 +};
53 +
54 +```
55 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate-iife.js new
+16
@@ -0,0 +1,16 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(a) {
4 + let x = { a };
5 + let y = {};
6 + (function () {
7 + y["x"] = x;
8 + })();
9 + mutate(y);
10 + return y;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: component,
15 + params: ["foo"],
16 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function component(a) {
6 let x = { a };
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y["x"] = x;
10 - })();
10 + };
11 + f0();
12 mutate(y);
13 return y;
14 }
@@ -25,9 +26,11 @@ function component(a) {
26 if (c_0) {
27 const x = { a };
28 y = {};
28 - (function () {
29 + const f0 = function () {
30 y.x = x;
30 - })();
31 + };
32 +
33 + f0();
34 mutate(y);
35 $[0] = a;
36 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate.js
+3 -2
@@ -1,9 +1,10 @@
1 function component(a) {
2 let x = { a };
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y["x"] = x;
6 - })();
6 + };
7 + f0();
8 mutate(y);
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-mutate-iife.expect.md new
+55
@@ -0,0 +1,55 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(a) {
8 + let x = { a };
9 + let y = {};
10 + (function () {
11 + y.x = x;
12 + })();
13 + mutate(y);
14 + return y;
15 +}
16 +
17 +export const FIXTURE_ENTRYPOINT = {
18 + fn: component,
19 + params: ["foo"],
20 +};
21 +
22 +```
23 +
24 +## Code
25 +
26 +```javascript
27 +import { unstable_useMemoCache as useMemoCache } from "react";
28 +const { mutate } = require("shared-runtime");
29 +
30 +function component(a) {
31 + const $ = useMemoCache(2);
32 + const c_0 = $[0] !== a;
33 + let y;
34 + if (c_0) {
35 + const x = { a };
36 + y = {};
37 +
38 + y.x = x;
39 +
40 + mutate(y);
41 + $[0] = a;
42 + $[1] = y;
43 + } else {
44 + y = $[1];
45 + }
46 + return y;
47 +}
48 +
49 +export const FIXTURE_ENTRYPOINT = {
50 + fn: component,
51 + params: ["foo"],
52 +};
53 +
54 +```
55 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-mutate-iife.js new
+16
@@ -0,0 +1,16 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(a) {
4 + let x = { a };
5 + let y = {};
6 + (function () {
7 + y.x = x;
8 + })();
9 + mutate(y);
10 + return y;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: component,
15 + params: ["foo"],
16 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-mutate.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function component(a) {
6 let x = { a };
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y.x = x;
10 - })();
10 + };
11 + f0();
12 mutate(y);
13 return y;
14 }
@@ -25,9 +26,11 @@ function component(a) {
26 if (c_0) {
27 const x = { a };
28 y = {};
28 - (function () {
29 + const f0 = function () {
30 y.x = x;
30 - })();
31 + };
32 +
33 + f0();
34 mutate(y);
35 $[0] = a;
36 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-mutate.js
+3 -2
@@ -1,9 +1,10 @@
1 function component(a) {
2 let x = { a };
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y.x = x;
6 - })();
6 + };
7 + f0();
8 mutate(y);
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate-iife.expect.md new
+57
@@ -0,0 +1,57 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { mutate } from "shared-runtime";
6 +
7 +function component(a) {
8 + let x = { a };
9 + let y = {};
10 + (function () {
11 + let a = y;
12 + a["x"] = x;
13 + })();
14 + mutate(y);
15 + return y;
16 +}
17 +
18 +export const FIXTURE_ENTRYPOINT = {
19 + fn: component,
20 + params: ["foo"],
21 +};
22 +
23 +```
24 +
25 +## Code
26 +
27 +```javascript
28 +import { unstable_useMemoCache as useMemoCache } from "react";
29 +import { mutate } from "shared-runtime";
30 +
31 +function component(a) {
32 + const $ = useMemoCache(2);
33 + const c_0 = $[0] !== a;
34 + let y;
35 + if (c_0) {
36 + const x = { a };
37 + y = {};
38 +
39 + const a_0 = y;
40 + a_0.x = x;
41 +
42 + mutate(y);
43 + $[0] = a;
44 + $[1] = y;
45 + } else {
46 + y = $[1];
47 + }
48 + return y;
49 +}
50 +
51 +export const FIXTURE_ENTRYPOINT = {
52 + fn: component,
53 + params: ["foo"],
54 +};
55 +
56 +```
57 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate-iife.js new
+17
@@ -0,0 +1,17 @@
1 +import { mutate } from "shared-runtime";
2 +
3 +function component(a) {
4 + let x = { a };
5 + let y = {};
6 + (function () {
7 + let a = y;
8 + a["x"] = x;
9 + })();
10 + mutate(y);
11 + return y;
12 +}
13 +
14 +export const FIXTURE_ENTRYPOINT = {
15 + fn: component,
16 + params: ["foo"],
17 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate.expect.md
+7 -4
@@ -5,10 +5,11 @@
5 function component(a) {
6 let x = { a };
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 let a = y;
10 a["x"] = x;
11 - })();
11 + };
12 + f0();
13 mutate(y);
14 return y;
15 }
@@ -26,10 +27,12 @@ function component(a) {
27 if (c_0) {
28 const x = { a };
29 y = {};
29 - (function () {
30 + const f0 = function () {
31 const a_0 = y;
32 a_0.x = x;
32 - })();
33 + };
34 +
35 + f0();
36 mutate(y);
37 $[0] = a;
38 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate.js
+3 -2
@@ -1,10 +1,11 @@
1 function component(a) {
2 let x = { a };
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 let a = y;
6 a["x"] = x;
7 - })();
7 + };
8 + f0();
9 mutate(y);
10 return y;
11 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate-iife.expect.md new
+57
@@ -0,0 +1,57 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(a) {
8 + let x = { a };
9 + let y = {};
10 + (function () {
11 + let a = y;
12 + a.x = x;
13 + })();
14 + mutate(y);
15 + return y;
16 +}
17 +
18 +export const FIXTURE_ENTRYPOINT = {
19 + fn: component,
20 + params: ["foo"],
21 +};
22 +
23 +```
24 +
25 +## Code
26 +
27 +```javascript
28 +import { unstable_useMemoCache as useMemoCache } from "react";
29 +const { mutate } = require("shared-runtime");
30 +
31 +function component(a) {
32 + const $ = useMemoCache(2);
33 + const c_0 = $[0] !== a;
34 + let y;
35 + if (c_0) {
36 + const x = { a };
37 + y = {};
38 +
39 + const a_0 = y;
40 + a_0.x = x;
41 +
42 + mutate(y);
43 + $[0] = a;
44 + $[1] = y;
45 + } else {
46 + y = $[1];
47 + }
48 + return y;
49 +}
50 +
51 +export const FIXTURE_ENTRYPOINT = {
52 + fn: component,
53 + params: ["foo"],
54 +};
55 +
56 +```
57 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate-iife.js new
+17
@@ -0,0 +1,17 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(a) {
4 + let x = { a };
5 + let y = {};
6 + (function () {
7 + let a = y;
8 + a.x = x;
9 + })();
10 + mutate(y);
11 + return y;
12 +}
13 +
14 +export const FIXTURE_ENTRYPOINT = {
15 + fn: component,
16 + params: ["foo"],
17 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate.expect.md
+7 -4
@@ -5,10 +5,11 @@
5 function component(a) {
6 let x = { a };
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 let a = y;
10 a.x = x;
11 - })();
11 + };
12 + f0();
13 mutate(y);
14 return y;
15 }
@@ -26,10 +27,12 @@ function component(a) {
27 if (c_0) {
28 const x = { a };
29 y = {};
29 - (function () {
30 + const f0 = function () {
31 const a_0 = y;
32 a_0.x = x;
32 - })();
33 + };
34 +
35 + f0();
36 mutate(y);
37 $[0] = a;
38 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate.js
+3 -2
@@ -1,10 +1,11 @@
1 function component(a) {
2 let x = { a };
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 let a = y;
6 a.x = x;
7 - })();
7 + };
8 + f0();
9 mutate(y);
10 return y;
11 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md new
+56
@@ -0,0 +1,56 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +const { mutate } = require("shared-runtime");
6 +
7 +function component(a) {
8 + let x = { a };
9 + let y = {};
10 + (function () {
11 + y = x;
12 + })();
13 + mutate(y);
14 + return y;
15 +}
16 +
17 +export const FIXTURE_ENTRYPOINT = {
18 + fn: component,
19 + params: ["foo"],
20 +};
21 +
22 +```
23 +
24 +## Code
25 +
26 +```javascript
27 +import { unstable_useMemoCache as useMemoCache } from "react";
28 +const { mutate } = require("shared-runtime");
29 +
30 +function component(a) {
31 + const $ = useMemoCache(2);
32 + const c_0 = $[0] !== a;
33 + let y;
34 + if (c_0) {
35 + const x = { a };
36 + y = {};
37 +
38 + y;
39 + y = x;
40 +
41 + mutate(y);
42 + $[0] = a;
43 + $[1] = y;
44 + } else {
45 + y = $[1];
46 + }
47 + return y;
48 +}
49 +
50 +export const FIXTURE_ENTRYPOINT = {
51 + fn: component,
52 + params: ["foo"],
53 +};
54 +
55 +```
56 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.js new
+16
@@ -0,0 +1,16 @@
1 +const { mutate } = require("shared-runtime");
2 +
3 +function component(a) {
4 + let x = { a };
5 + let y = {};
6 + (function () {
7 + y = x;
8 + })();
9 + mutate(y);
10 + return y;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: component,
15 + params: ["foo"],
16 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-simple-alias.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function component(a) {
6 let x = { a };
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y = x;
10 - })();
10 + };
11 + f0();
12 mutate(y);
13 return y;
14 }
@@ -25,9 +26,11 @@ function component(a) {
26 if (c_0) {
27 const x = { a };
28 y = {};
28 - (function () {
29 + const f0 = function () {
30 y = x;
30 - })();
31 + };
32 +
33 + f0();
34 mutate(y);
35 $[0] = a;
36 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-func-simple-alias.js
+3 -2
@@ -1,9 +1,10 @@
1 function component(a) {
2 let x = { a };
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y = x;
6 - })();
6 + };
7 + f0();
8 mutate(y);
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function bar(a) {
6 + let x = [a];
7 + let y = {};
8 + (function () {
9 + y = x[0][1];
10 + })();
11 +
12 + return y;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: bar,
17 + params: [["val1", "val2"]],
18 + isComponent: false,
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { unstable_useMemoCache as useMemoCache } from "react";
27 +function bar(a) {
28 + const $ = useMemoCache(2);
29 + const c_0 = $[0] !== a;
30 + let y;
31 + if (c_0) {
32 + const x = [a];
33 + y = {};
34 +
35 + y;
36 + y = x[0][1];
37 + $[0] = a;
38 + $[1] = y;
39 + } else {
40 + y = $[1];
41 + }
42 + return y;
43 +}
44 +
45 +export const FIXTURE_ENTRYPOINT = {
46 + fn: bar,
47 + params: [["val1", "val2"]],
48 + isComponent: false,
49 +};
50 +
51 +```
52 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.js new
+15
@@ -0,0 +1,15 @@
1 +function bar(a) {
2 + let x = [a];
3 + let y = {};
4 + (function () {
5 + y = x[0][1];
6 + })();
7 +
8 + return y;
9 +}
10 +
11 +export const FIXTURE_ENTRYPOINT = {
12 + fn: bar,
13 + params: [["val1", "val2"]],
14 + isComponent: false,
15 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function bar(a) {
6 let x = [a];
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y = x[0][1];
10 - })();
10 + };
11 + f0();
12
13 return y;
14 }
@@ -31,9 +32,11 @@ function bar(a) {
32 if (c_0) {
33 const x = [a];
34 y = {};
34 - (function () {
35 + const f0 = function () {
36 y = x[0][1];
36 - })();
37 + };
38 +
39 + f0();
40 $[0] = a;
41 $[1] = y;
42 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2.js
+3 -2
@@ -1,9 +1,10 @@
1 function bar(a) {
2 let x = [a];
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y = x[0][1];
6 - })();
6 + };
7 + f0();
8
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md new
+60
@@ -0,0 +1,60 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function bar(a, b) {
6 + let x = [a, b];
7 + let y = {};
8 + let t = {};
9 + (function () {
10 + y = x[0][1];
11 + t = x[1][0];
12 + })();
13 +
14 + return y;
15 +}
16 +
17 +export const FIXTURE_ENTRYPOINT = {
18 + fn: bar,
19 + params: ["TodoAdd"],
20 + isComponent: "TodoAdd",
21 +};
22 +
23 +```
24 +
25 +## Code
26 +
27 +```javascript
28 +import { unstable_useMemoCache as useMemoCache } from "react";
29 +function bar(a, b) {
30 + const $ = useMemoCache(3);
31 + const c_0 = $[0] !== a;
32 + const c_1 = $[1] !== b;
33 + let y;
34 + if (c_0 || c_1) {
35 + const x = [a, b];
36 + y = {};
37 + let t;
38 + t = {};
39 +
40 + y;
41 + t;
42 + y = x[0][1];
43 + t = x[1][0];
44 + $[0] = a;
45 + $[1] = b;
46 + $[2] = y;
47 + } else {
48 + y = $[2];
49 + }
50 + return y;
51 +}
52 +
53 +export const FIXTURE_ENTRYPOINT = {
54 + fn: bar,
55 + params: ["TodoAdd"],
56 + isComponent: "TodoAdd",
57 +};
58 +
59 +```
60 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.js new
+17
@@ -0,0 +1,17 @@
1 +function bar(a, b) {
2 + let x = [a, b];
3 + let y = {};
4 + let t = {};
5 + (function () {
6 + y = x[0][1];
7 + t = x[1][0];
8 + })();
9 +
10 + return y;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: bar,
15 + params: ["TodoAdd"],
16 + isComponent: "TodoAdd",
17 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3.expect.md
+7 -4
@@ -6,10 +6,11 @@ function bar(a, b) {
6 let x = [a, b];
7 let y = {};
8 let t = {};
9 - (function () {
9 + const f0 = function () {
10 y = x[0][1];
11 t = x[1][0];
12 - })();
12 + };
13 + f0();
14
15 return y;
16 }
@@ -36,10 +37,12 @@ function bar(a, b) {
37 y = {};
38 let t;
39 t = {};
39 - (function () {
40 + const f0 = function () {
41 y = x[0][1];
42 t = x[1][0];
42 - })();
43 + };
44 +
45 + f0();
46 $[0] = a;
47 $[1] = b;
48 $[2] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3.js
+3 -2
@@ -2,10 +2,11 @@ function bar(a, b) {
2 let x = [a, b];
3 let y = {};
4 let t = {};
5 - (function () {
5 + const f0 = function () {
6 y = x[0][1];
7 t = x[1][0];
8 - })();
8 + };
9 + f0();
10
11 return y;
12 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function bar(a) {
6 + let x = [a];
7 + let y = {};
8 + (function () {
9 + y = x[0].a[1];
10 + })();
11 +
12 + return y;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: bar,
17 + params: [{ a: ["val1", "val2"] }],
18 + isComponent: false,
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { unstable_useMemoCache as useMemoCache } from "react";
27 +function bar(a) {
28 + const $ = useMemoCache(2);
29 + const c_0 = $[0] !== a;
30 + let y;
31 + if (c_0) {
32 + const x = [a];
33 + y = {};
34 +
35 + y;
36 + y = x[0].a[1];
37 + $[0] = a;
38 + $[1] = y;
39 + } else {
40 + y = $[1];
41 + }
42 + return y;
43 +}
44 +
45 +export const FIXTURE_ENTRYPOINT = {
46 + fn: bar,
47 + params: [{ a: ["val1", "val2"] }],
48 + isComponent: false,
49 +};
50 +
51 +```
52 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.js new
+15
@@ -0,0 +1,15 @@
1 +function bar(a) {
2 + let x = [a];
3 + let y = {};
4 + (function () {
5 + y = x[0].a[1];
6 + })();
7 +
8 + return y;
9 +}
10 +
11 +export const FIXTURE_ENTRYPOINT = {
12 + fn: bar,
13 + params: [{ a: ["val1", "val2"] }],
14 + isComponent: false,
15 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function bar(a) {
6 let x = [a];
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y = x[0].a[1];
10 - })();
10 + };
11 + f0();
12
13 return y;
14 }
@@ -31,9 +32,11 @@ function bar(a) {
32 if (c_0) {
33 const x = [a];
34 y = {};
34 - (function () {
35 + const f0 = function () {
36 y = x[0].a[1];
36 - })();
37 + };
38 +
39 + f0();
40 $[0] = a;
41 $[1] = y;
42 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4.js
+3 -2
@@ -1,9 +1,10 @@
1 function bar(a) {
2 let x = [a];
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y = x[0].a[1];
6 - })();
6 + };
7 + f0();
8
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function bar(a) {
6 + let x = [a];
7 + let y = {};
8 + (function () {
9 + y = x[0];
10 + })();
11 +
12 + return y;
13 +}
14 +
15 +export const FIXTURE_ENTRYPOINT = {
16 + fn: bar,
17 + params: ["TodoAdd"],
18 + isComponent: "TodoAdd",
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { unstable_useMemoCache as useMemoCache } from "react";
27 +function bar(a) {
28 + const $ = useMemoCache(2);
29 + const c_0 = $[0] !== a;
30 + let y;
31 + if (c_0) {
32 + const x = [a];
33 + y = {};
34 +
35 + y;
36 + y = x[0];
37 + $[0] = a;
38 + $[1] = y;
39 + } else {
40 + y = $[1];
41 + }
42 + return y;
43 +}
44 +
45 +export const FIXTURE_ENTRYPOINT = {
46 + fn: bar,
47 + params: ["TodoAdd"],
48 + isComponent: "TodoAdd",
49 +};
50 +
51 +```
52 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.js new
+15
@@ -0,0 +1,15 @@
1 +function bar(a) {
2 + let x = [a];
3 + let y = {};
4 + (function () {
5 + y = x[0];
6 + })();
7 +
8 + return y;
9 +}
10 +
11 +export const FIXTURE_ENTRYPOINT = {
12 + fn: bar,
13 + params: ["TodoAdd"],
14 + isComponent: "TodoAdd",
15 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load.expect.md
+7 -4
@@ -5,9 +5,10 @@
5 function bar(a) {
6 let x = [a];
7 let y = {};
8 - (function () {
8 + const f0 = function () {
9 y = x[0];
10 - })();
10 + };
11 + f0();
12
13 return y;
14 }
@@ -31,9 +32,11 @@ function bar(a) {
32 if (c_0) {
33 const x = [a];
34 y = {};
34 - (function () {
35 + const f0 = function () {
36 y = x[0];
36 - })();
37 + };
38 +
39 + f0();
40 $[0] = a;
41 $[1] = y;
42 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load.js
+3 -2
@@ -1,9 +1,10 @@
1 function bar(a) {
2 let x = [a];
3 let y = {};
4 - (function () {
4 + const f0 = function () {
5 y = x[0];
6 - })();
6 + };
7 + f0();
8
9 return y;
10 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-capture-ref-before-rename.expect.md
+3 -3
@@ -29,14 +29,14 @@ function component(a, b) {
29 let z;
30 if (c_0) {
31 z = { a };
32 - (function () {
33 - mutate(z);
34 - })();
32 +
33 + mutate(z);
34 $[0] = a;
35 $[1] = z;
36 } else {
37 z = $[1];
38 }
39 +
40 let y = z;
41 const c_2 = $[2] !== b;
42 let t0;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-function-renamed-ref.expect.md
+2 -3
@@ -33,9 +33,8 @@ function component(a, b) {
33 const z = t0;
34
35 const z_0 = { b };
36 - (function () {
37 - mutate(z_0);
38 - })();
36 +
37 + mutate(z_0);
38 return z;
39 }
40
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md
+4 -3
@@ -25,9 +25,10 @@ function component(a) {
25 if (c_0) {
26 const x = { a };
27 y = 1;
28 - (function () {
29 - y = x;
30 - })();
28 +
29 + y;
30 + y = x;
31 +
32 mutate(y);
33 $[0] = a;
34 $[1] = y;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md
+3 -3
@@ -27,14 +27,14 @@ function f(a) {
27 const c_0 = $[0] !== a;
28 let x;
29 if (c_0) {
30 - (() => {
31 - x = { a };
32 - })();
30 + x;
31 + x = { a };
32 $[0] = a;
33 $[1] = x;
34 } else {
35 x = $[1];
36 }
37 +
38 const t0 = x;
39 const c_2 = $[2] !== t0;
40 let t1;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md
+2 -3
@@ -27,9 +27,8 @@ function f(a) {
27 const $ = useMemoCache(2);
28 let x;
29 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 - (() => {
31 - x = {};
32 - })();
30 + x;
31 + x = {};
32 $[0] = x;
33 } else {
34 x = $[0];
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/nested-function-with-param-as-captured-dep.expect.md
+7 -14
@@ -24,27 +24,20 @@ export const FIXTURE_ENTRYPOINT = {
24 ```javascript
25 import { unstable_useMemoCache as useMemoCache } from "react";
26 function Foo() {
27 - const $ = useMemoCache(2);
27 + const $ = useMemoCache(1);
28 + let t38;
29 let t0;
30 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 - t0 = function t() {
31 - return function a(t25) {
32 - const x_0 = t25 === undefined ? () => {} : t25;
33 - return x_0;
34 - };
31 + t0 = function a(t25) {
32 + const x_0 = t25 === undefined ? () => {} : t25;
33 + return x_0;
34 };
35 $[0] = t0;
36 } else {
37 t0 = $[0];
38 }
40 - let t1;
41 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
42 - t1 = t0();
43 - $[1] = t1;
44 - } else {
45 - t1 = $[1];
46 - }
47 - return t1;
39 + t38 = t0;
40 + return t38;
41 }
42
43 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/recursive-function-expr.expect.md
+1 -1
@@ -12,7 +12,7 @@ function foo() {
12
13 ```javascript
14 function foo() {
15 - (() => foo())();
15 + foo();
16 }
17
18 ```
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-duplicate-instruction-from-merge-consecutive-scopes.expect.md
+15 -20
@@ -26,38 +26,33 @@ export const FIXTURE_ENTRYPOINT = {
26 ```javascript
27 import { unstable_useMemoCache as useMemoCache } from "react"; // @enableMergeConsecutiveScopes
28 function Component(id) {
29 - const $ = useMemoCache(4);
29 + const $ = useMemoCache(3);
30 + let t25;
31 + t25 = undefined;
32 + const bar = t25;
33 let t0;
34 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 - t0 = (() => {})();
35 + t0 = <Bar title={bar} />;
36 $[0] = t0;
37 } else {
38 t0 = $[0];
39 }
37 - const bar = t0;
38 - let t1;
39 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
40 - t1 = <Bar title={bar} />;
41 - $[1] = t1;
42 - } else {
43 - t1 = $[1];
44 - }
45 - const t2 = id ? true : false;
46 - const c_2 = $[2] !== t2;
47 - let t3;
48 - if (c_2) {
49 - t3 = (
40 + const t1 = id ? true : false;
41 + const c_1 = $[1] !== t1;
42 + let t2;
43 + if (c_1) {
44 + t2 = (
45 <>
51 - {t1}
52 - <Bar title={t2} />
46 + {t0}
47 + <Bar title={t1} />
48 </>
49 );
50 + $[1] = t1;
51 $[2] = t2;
56 - $[3] = t3;
52 } else {
58 - t3 = $[3];
53 + t2 = $[2];
54 }
60 - return t3;
55 + return t2;
56 }
57
58 export const FIXTURE_ENTRYPOINT = {