@samitouri / QOS-React-2 / commits / 23e0ce02a6

Make JSX memoization optional (on by default)

Makes JSX memoized by default again, but adds an option to disable memoization of JSX. Also adds a new test and fixtures directory to test the opt-in no-jsx-memoization behavior.

Joe Savona committed Mar 13, 2023 at 13:25 UTC 23e0ce02a61e57360b4eed57e4fdc38e43a2efbd
46 files changed +894 -193
compiler/forget/src/CompilerPipeline.ts
+3 -1
@@ -146,7 +146,9 @@ export function* run(
146 value: reactiveFunction,
147 });
148
149 - pruneNonEscapingScopes(reactiveFunction);
149 + pruneNonEscapingScopes(reactiveFunction, {
150 + memoizeJsxElements: options?.memoizeJsxElements ?? true,
151 + });
152 yield log({
153 kind: "reactive",
154 name: "PruneNonEscapingDependencies",
compiler/forget/src/HIR/Environment.ts
+2
@@ -8,11 +8,13 @@ const HOOK_PATTERN = /^_?use/;
8 export type EnvironmentOptions = {
9 customHooks: Map<string, Hook>;
10 globals: Set<string>;
11 + memoizeJsxElements: boolean;
12 };
13
14 const DEFAULT_OPTIONS: EnvironmentOptions = {
15 customHooks: new Map(),
16 globals: DEFAULT_GLOBALS,
17 + memoizeJsxElements: true,
18 };
19
20 export function mergeOptions(
compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts
+33 -17
@@ -102,7 +102,10 @@ import {
102 * conditional node with an aliased dep promotes to aliased).
103 * 4. Finally we prune scopes whose outputs weren't marked.
104 */
105 -export function pruneNonEscapingScopes(fn: ReactiveFunction): void {
105 +export function pruneNonEscapingScopes(
106 + fn: ReactiveFunction,
107 + options: MemoizationOptions
108 +): void {
109 // First build up a map of which instructions are involved in creating which values,
110 // and which values are returned.
111 const state = new State();
@@ -112,7 +115,7 @@ export function pruneNonEscapingScopes(fn: ReactiveFunction): void {
115 for (const param of fn.params) {
116 state.declare(param.identifier.id);
117 }
115 - visitReactiveFunction(fn, new CollectDependenciesVisitor(), state);
118 + visitReactiveFunction(fn, new CollectDependenciesVisitor(options), state);
119
120 log(() => prettyFormat(state));
121
@@ -128,6 +131,10 @@ export function pruneNonEscapingScopes(fn: ReactiveFunction): void {
131 visitReactiveFunction(fn, new PruneScopesTransform(), memoized);
132 }
133
134 +export type MemoizationOptions = {
135 + memoizeJsxElements: boolean;
136 +};
137 +
138 // Describes how to determine whether a value should be memoized, relative to dependees and dependencies
139 enum MemoizationLevel {
140 // The value should be memoized if it escapes
@@ -316,7 +323,8 @@ type LValueMemoization = {
323 */
324 function computeMemoizationInputs(
325 value: ReactiveValue,
319 - lvalue: Place | null
326 + lvalue: Place | null,
327 + options: MemoizationOptions
328 ): {
329 // can optionally return a custom set of lvalues per instruction
330 lvalues: Array<LValueMemoization>;
@@ -332,8 +340,8 @@ function computeMemoizationInputs(
340 : [],
341 rvalues: [
342 // Conditionals do not alias their test value.
335 - ...computeMemoizationInputs(value.consequent, null).rvalues,
336 - ...computeMemoizationInputs(value.alternate, null).rvalues,
343 + ...computeMemoizationInputs(value.consequent, null, options).rvalues,
344 + ...computeMemoizationInputs(value.alternate, null, options).rvalues,
345 ],
346 };
347 }
@@ -345,8 +353,8 @@ function computeMemoizationInputs(
353 ? [{ place: lvalue, level: MemoizationLevel.Conditional }]
354 : [],
355 rvalues: [
348 - ...computeMemoizationInputs(value.left, null).rvalues,
349 - ...computeMemoizationInputs(value.right, null).rvalues,
356 + ...computeMemoizationInputs(value.left, null, options).rvalues,
357 + ...computeMemoizationInputs(value.right, null, options).rvalues,
358 ],
359 };
360 }
@@ -360,7 +368,7 @@ function computeMemoizationInputs(
368 // Only the final value of the sequence is a true rvalue:
369 // values from the sequence's instructions are evaluated
370 // as separate nodes
363 - rvalues: computeMemoizationInputs(value.value, null).rvalues,
371 + rvalues: computeMemoizationInputs(value.value, null, options).rvalues,
372 };
373 }
374 case "JsxExpression": {
@@ -378,24 +386,24 @@ function computeMemoizationInputs(
386 operands.push(child);
387 }
388 }
389 + const level = options.memoizeJsxElements
390 + ? MemoizationLevel.Memoized
391 + : MemoizationLevel.Unmemoized;
392 return {
393 // JSX elements themselves are not memoized unless forced to
394 // avoid breaking downstream memoization
384 - lvalues:
385 - lvalue !== null
386 - ? [{ place: lvalue, level: MemoizationLevel.Unmemoized }]
387 - : [],
395 + lvalues: lvalue !== null ? [{ place: lvalue, level }] : [],
396 rvalues: operands,
397 };
398 }
399 case "JsxFragment": {
400 + const level = options.memoizeJsxElements
401 + ? MemoizationLevel.Memoized
402 + : MemoizationLevel.Unmemoized;
403 return {
404 // JSX elements themselves are not memoized unless forced to
405 // avoid breaking downstream memoization
395 - lvalues:
396 - lvalue !== null
397 - ? [{ place: lvalue, level: MemoizationLevel.Unmemoized }]
398 - : [],
406 + lvalues: lvalue !== null ? [{ place: lvalue, level }] : [],
407 rvalues: value.children,
408 };
409 }
@@ -564,6 +572,13 @@ function computePatternLValues(pattern: Pattern): Array<LValueMemoization> {
572 * identifier's and scope's dependencies.
573 */
574 class CollectDependenciesVisitor extends ReactiveFunctionVisitor<State> {
575 + options: MemoizationOptions;
576 +
577 + constructor(options: MemoizationOptions) {
578 + super();
579 + this.options = options;
580 + }
581 +
582 override visitInstruction(
583 instruction: ReactiveInstruction,
584 state: State
@@ -573,7 +588,8 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor<State> {
588 // Determe the level of memoization for this value and the lvalues/rvalues
589 const aliasing = computeMemoizationInputs(
590 instruction.value,
576 - instruction.lvalue
591 + instruction.lvalue,
592 + this.options
593 );
594
595 // Associate all the rvalues with the instruction's scope if it has one
compiler/forget/src/__tests__/compiler-test.ts
+1 -1
@@ -28,7 +28,7 @@ wasmFolder(
28 path.join(__dirname, "..", "..", "node_modules", "@hpcc-js", "wasm", "dist")
29 );
30
31 -describe("React Forget (HIR version)", () => {
31 +describe("React Forget", () => {
32 generateTestsFromFixtures(
33 path.join(__dirname, "fixtures", "compiler"),
34 (input, file, options) => {
compiler/forget/src/__tests__/disableMemoizeJsxElements-test.ts new
+110
@@ -0,0 +1,110 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its 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 +"use strict";
9 +
10 +import path from "path";
11 +import runReactForgetBabelPlugin from "../Babel/RunReactForgetBabelPlugin";
12 +import { Effect, ValueKind } from "../index";
13 +import { toggleLogging } from "../Utils/logger";
14 +import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
15 +
16 +type TestOutput = {
17 + js: string;
18 +};
19 +
20 +function wrapWithTripleBackticks(s: string, ext?: string) {
21 + return `\`\`\`${ext ?? ""}
22 +${s}
23 +\`\`\``;
24 +}
25 +
26 +describe("React Forget (Disable memoization of JSX elements)", () => {
27 + generateTestsFromFixtures(
28 + path.join(__dirname, "fixtures", "disableMemoizeJsxElements"),
29 + (input, file, options) => {
30 + let items: Array<TestOutput> = [];
31 + let error: Error | null = null;
32 + if (options.debug) {
33 + toggleLogging(options.debug);
34 + }
35 + try {
36 + items.push({
37 + js: runReactForgetBabelPlugin(input, file, options.language, {
38 + enableOnlyOnUseForgetDirective:
39 + options.enableOnlyOnUseForgetDirective,
40 + environment: {
41 + memoizeJsxElements: false,
42 + customHooks: new Map([
43 + [
44 + "useFreeze",
45 + {
46 + name: "useFreeze",
47 + kind: "Custom",
48 + valueKind: ValueKind.Frozen,
49 + effectKind: Effect.Freeze,
50 + },
51 + ],
52 + ]),
53 + },
54 + logger: null,
55 + gatingModule: options.gatingModule,
56 + }).code,
57 + });
58 + } catch (e) {
59 + error = e;
60 + }
61 + let outputs: Array<string>;
62 +
63 + const expectError = file.startsWith("error.");
64 + if (expectError) {
65 + if (error === null) {
66 + throw new Error(
67 + `Expected an error to be thrown for fixture: '${file}', remove the 'error.' prefix if an error is not expected.`
68 + );
69 + } else {
70 + outputs = [formatErrorOutput(error)];
71 + }
72 + } else {
73 + if (error !== null) {
74 + error.message = `Expected fixture '${file}' to succeed but it failed with error:\n\n${error.message}`;
75 + throw error;
76 + }
77 + if (items === null || items.length === 0) {
78 + throw new Error(`Expected at least one output for file '${file}'.`);
79 + }
80 + outputs = formatOutput(items);
81 + }
82 + return `
83 +## Input
84 +
85 +${wrapWithTripleBackticks(input, "javascript")}
86 +
87 +${outputs.join("\n")}
88 + `;
89 + }
90 + );
91 +});
92 +
93 +function formatErrorOutput(error: Error): string {
94 + error.message = error.message.replace(/^\/.*?:\s/, "");
95 + return `
96 +## Error
97 +
98 +${wrapWithTripleBackticks(error.message)}
99 + `;
100 +}
101 +
102 +function formatOutput(items: Array<TestOutput>): Array<string> {
103 + return items.map(({ js }) => {
104 + return `
105 +## Code
106 +
107 +${wrapWithTripleBackticks(js, "javascript")}
108 + `.trim();
109 + });
110 +}
compiler/forget/src/__tests__/fixtures/compiler/call.expect.md
+9 -2
@@ -21,7 +21,7 @@ function Component(props) {
21 function foo() {}
22
23 function Component(props) {
24 - const $ = React.unstable_useMemoCache(2);
24 + const $ = React.unstable_useMemoCache(3);
25 let a;
26 let b;
27 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -36,7 +36,14 @@ function Component(props) {
36 a = $[0];
37 b = $[1];
38 }
39 - return <div a={a} b={b}></div>;
39 + let t0;
40 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
41 + t0 = <div a={a} b={b}></div>;
42 + $[2] = t0;
43 + } else {
44 + t0 = $[2];
45 + }
46 + return t0;
47 }
48
49 ```
compiler/forget/src/__tests__/fixtures/compiler/capture-func-passed-to-jsx.expect.md
+11 -2
@@ -20,7 +20,7 @@ function component(a, b) {
20
21 ```javascript
22 function component(a, b) {
23 - const $ = React.unstable_useMemoCache(7);
23 + const $ = React.unstable_useMemoCache(9);
24 const c_0 = $[0] !== b;
25 let t0;
26 if (c_0) {
@@ -56,7 +56,16 @@ function component(a, b) {
56 t2 = $[6];
57 }
58 const x = t2;
59 - const t = <Foo x={x}></Foo>;
59 + const c_7 = $[7] !== x;
60 + let t3;
61 + if (c_7) {
62 + t3 = <Foo x={x}></Foo>;
63 + $[7] = x;
64 + $[8] = t3;
65 + } else {
66 + t3 = $[8];
67 + }
68 + const t = t3;
69 mutate(x);
70 return t;
71 }
compiler/forget/src/__tests__/fixtures/compiler/capturing-function-member-expr-call.expect.md
+13 -2
@@ -20,7 +20,7 @@ function component({ mutator }) {
20
21 ```javascript
22 function component(t27) {
23 - const $ = React.unstable_useMemoCache(4);
23 + const $ = React.unstable_useMemoCache(7);
24 const { mutator } = t27;
25 const c_0 = $[0] !== mutator;
26 let t0;
@@ -46,7 +46,18 @@ function component(t27) {
46 t1 = $[3];
47 }
48 const hide = t1;
49 - return <Foo poke={poke} hide={hide}></Foo>;
49 + const c_4 = $[4] !== poke;
50 + const c_5 = $[5] !== hide;
51 + let t2;
52 + if (c_4 || c_5) {
53 + t2 = <Foo poke={poke} hide={hide}></Foo>;
54 + $[4] = poke;
55 + $[5] = hide;
56 + $[6] = t2;
57 + } else {
58 + t2 = $[6];
59 + }
60 + return t2;
61 }
62
63 ```
compiler/forget/src/__tests__/fixtures/compiler/component.expect.md
+27 -7
@@ -35,7 +35,7 @@ function Component(props) {
35
36 ```javascript
37 function Component(props) {
38 - const $ = React.unstable_useMemoCache(3);
38 + const $ = React.unstable_useMemoCache(8);
39 const items = props.items;
40 const maxItems = props.maxItems;
41 const c_0 = $[0] !== maxItems;
@@ -65,12 +65,32 @@ function Component(props) {
65 }
66
67 const count = renderedItems.length;
68 - return (
69 - <div>
70 - {<h1>{count} Items</h1>}
71 - {renderedItems}
72 - </div>
73 - );
68 + const c_3 = $[3] !== count;
69 + let t0;
70 + if (c_3) {
71 + t0 = <h1>{count} Items</h1>;
72 + $[3] = count;
73 + $[4] = t0;
74 + } else {
75 + t0 = $[4];
76 + }
77 + const c_5 = $[5] !== t0;
78 + const c_6 = $[6] !== renderedItems;
79 + let t1;
80 + if (c_5 || c_6) {
81 + t1 = (
82 + <div>
83 + {t0}
84 + {renderedItems}
85 + </div>
86 + );
87 + $[5] = t0;
88 + $[6] = renderedItems;
89 + $[7] = t1;
90 + } else {
91 + t1 = $[7];
92 + }
93 + return t1;
94 }
95
96 ```
compiler/forget/src/__tests__/fixtures/compiler/concise-arrow-expr.expect.md
+11 -2
@@ -14,7 +14,7 @@ function component() {
14
15 ```javascript
16 function component() {
17 - const $ = React.unstable_useMemoCache(2);
17 + const $ = React.unstable_useMemoCache(4);
18 const [x, setX] = useState(0);
19 const c_0 = $[0] !== setX;
20 let t0;
@@ -26,7 +26,16 @@ function component() {
26 t0 = $[1];
27 }
28 const handler = t0;
29 - return <Foo handler={handler}></Foo>;
29 + const c_2 = $[2] !== handler;
30 + let t1;
31 + if (c_2) {
32 + t1 = <Foo handler={handler}></Foo>;
33 + $[2] = handler;
34 + $[3] = t1;
35 + } else {
36 + t1 = $[3];
37 + }
38 + return t1;
39 }
40
41 ```
compiler/forget/src/__tests__/fixtures/compiler/conditional-on-mutable.expect.md
+26 -4
@@ -35,7 +35,7 @@ function mayMutate() {}
35
36 ```javascript
37 function ComponentA(props) {
38 - const $ = React.unstable_useMemoCache(3);
38 + const $ = React.unstable_useMemoCache(6);
39 const c_0 = $[0] !== props;
40 let a;
41 let b;
@@ -55,11 +55,22 @@ function ComponentA(props) {
55 a = $[1];
56 b = $[2];
57 }
58 - return <Foo a={a} b={b}></Foo>;
58 + const c_3 = $[3] !== a;
59 + const c_4 = $[4] !== b;
60 + let t0;
61 + if (c_3 || c_4) {
62 + t0 = <Foo a={a} b={b}></Foo>;
63 + $[3] = a;
64 + $[4] = b;
65 + $[5] = t0;
66 + } else {
67 + t0 = $[5];
68 + }
69 + return t0;
70 }
71
72 function ComponentB(props) {
62 - const $ = React.unstable_useMemoCache(3);
73 + const $ = React.unstable_useMemoCache(6);
74 const c_0 = $[0] !== props;
75 let a;
76 let b;
@@ -79,7 +90,18 @@ function ComponentB(props) {
90 a = $[1];
91 b = $[2];
92 }
82 - return <Foo a={a} b={b}></Foo>;
93 + const c_3 = $[3] !== a;
94 + const c_4 = $[4] !== b;
95 + let t0;
96 + if (c_3 || c_4) {
97 + t0 = <Foo a={a} b={b}></Foo>;
98 + $[3] = a;
99 + $[4] = b;
100 + $[5] = t0;
101 + } else {
102 + t0 = $[5];
103 + }
104 + return t0;
105 }
106
107 function Foo() {}
compiler/forget/src/__tests__/fixtures/compiler/constructor.expect.md
+9 -2
@@ -21,7 +21,7 @@ function Component(props) {
21 function Foo() {}
22
23 function Component(props) {
24 - const $ = React.unstable_useMemoCache(2);
24 + const $ = React.unstable_useMemoCache(3);
25 let a;
26 let b;
27 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -35,7 +35,14 @@ function Component(props) {
35 a = $[0];
36 b = $[1];
37 }
38 - return <div a={a} b={b}></div>;
38 + let t0;
39 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
40 + t0 = <div a={a} b={b}></div>;
41 + $[2] = t0;
42 + } else {
43 + t0 = $[2];
44 + }
45 + return t0;
46 }
47
48 ```
compiler/forget/src/__tests__/fixtures/compiler/controlled-input.expect.md
+13 -2
@@ -14,7 +14,7 @@ function component() {
14
15 ```javascript
16 function component() {
17 - const $ = React.unstable_useMemoCache(2);
17 + const $ = React.unstable_useMemoCache(5);
18 const [x, setX] = useState(0);
19 const c_0 = $[0] !== setX;
20 let t0;
@@ -26,7 +26,18 @@ function component() {
26 t0 = $[1];
27 }
28 const handler = t0;
29 - return <input onChange={handler} value={x}></input>;
29 + const c_2 = $[2] !== handler;
30 + const c_3 = $[3] !== x;
31 + let t1;
32 + if (c_2 || c_3) {
33 + t1 = <input onChange={handler} value={x}></input>;
34 + $[2] = handler;
35 + $[3] = x;
36 + $[4] = t1;
37 + } else {
38 + t1 = $[4];
39 + }
40 + return t1;
41 }
42
43 ```
compiler/forget/src/__tests__/fixtures/compiler/escape-analysis-destructured-rest-element.expect.md
+13 -2
@@ -16,7 +16,7 @@ function Component(props) {
16
17 ```javascript
18 function Component(props) {
19 - const $ = React.unstable_useMemoCache(4);
19 + const $ = React.unstable_useMemoCache(7);
20 const c_0 = $[0] !== props.a;
21 let b;
22 if (c_0) {
@@ -35,7 +35,18 @@ function Component(props) {
35 } else {
36 d = $[3];
37 }
38 - return <div b={b} d={d}></div>;
38 + const c_4 = $[4] !== b;
39 + const c_5 = $[5] !== d;
40 + let t0;
41 + if (c_4 || c_5) {
42 + t0 = <div b={b} d={d}></div>;
43 + $[4] = b;
44 + $[5] = d;
45 + $[6] = t0;
46 + } else {
47 + t0 = $[6];
48 + }
49 + return t0;
50 }
51
52 ```
compiler/forget/src/__tests__/fixtures/compiler/escape-analysis-jsx-child.expect.md
+11 -3
@@ -20,7 +20,7 @@ function foo(a, b, c) {
20
21 ```javascript
22 function foo(a, b, c) {
23 - const $ = React.unstable_useMemoCache(7);
23 + const $ = React.unstable_useMemoCache(9);
24 const c_0 = $[0] !== a;
25 const c_1 = $[1] !== b;
26 const c_2 = $[2] !== c;
@@ -42,8 +42,16 @@ function foo(a, b, c) {
42 } else {
43 y = $[6];
44 }
45 -
46 - x.push(<div>{y}</div>);
45 + const c_7 = $[7] !== y;
46 + let t0;
47 + if (c_7) {
48 + t0 = <div>{y}</div>;
49 + $[7] = y;
50 + $[8] = t0;
51 + } else {
52 + t0 = $[8];
53 + }
54 + x.push(t0);
55 }
56 $[0] = a;
57 $[1] = b;
compiler/forget/src/__tests__/fixtures/compiler/gating-test-export-default-function.expect.md
+22 -2
@@ -28,7 +28,17 @@ function Bar_uncompiled(props) {
28 return <div>{props.bar}</div>;
29 }
30 function Bar_forget(props) {
31 - return <div>{props.bar}</div>;
31 + const $ = React.unstable_useMemoCache(2);
32 + const c_0 = $[0] !== props.bar;
33 + let t0;
34 + if (c_0) {
35 + t0 = <div>{props.bar}</div>;
36 + $[0] = props.bar;
37 + $[1] = t0;
38 + } else {
39 + t0 = $[1];
40 + }
41 + return t0;
42 }
43 const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
44 export default Bar;
@@ -42,7 +52,17 @@ function Foo_uncompiled(props) {
52 return <Foo>{props.bar}</Foo>;
53 }
54 function Foo_forget(props) {
45 - return <Foo>{props.bar}</Foo>;
55 + const $ = React.unstable_useMemoCache(2);
56 + const c_0 = $[0] !== props.bar;
57 + let t0;
58 + if (c_0) {
59 + t0 = <Foo>{props.bar}</Foo>;
60 + $[0] = props.bar;
61 + $[1] = t0;
62 + } else {
63 + t0 = $[1];
64 + }
65 + return t0;
66 }
67 const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
68
compiler/forget/src/__tests__/fixtures/compiler/gating-test-export-function-and-default.expect.md
+22 -2
@@ -28,7 +28,17 @@ function Bar_uncompiled(props) {
28 return <div>{props.bar}</div>;
29 }
30 function Bar_forget(props) {
31 - return <div>{props.bar}</div>;
31 + const $ = React.unstable_useMemoCache(2);
32 + const c_0 = $[0] !== props.bar;
33 + let t0;
34 + if (c_0) {
35 + t0 = <div>{props.bar}</div>;
36 + $[0] = props.bar;
37 + $[1] = t0;
38 + } else {
39 + t0 = $[1];
40 + }
41 + return t0;
42 }
43 const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
44 export default Bar;
@@ -42,7 +52,17 @@ function Foo_uncompiled(props) {
52 return <Foo>{props.bar}</Foo>;
53 }
54 function Foo_forget(props) {
45 - return <Foo>{props.bar}</Foo>;
55 + const $ = React.unstable_useMemoCache(2);
56 + const c_0 = $[0] !== props.bar;
57 + let t0;
58 + if (c_0) {
59 + t0 = <Foo>{props.bar}</Foo>;
60 + $[0] = props.bar;
61 + $[1] = t0;
62 + } else {
63 + t0 = $[1];
64 + }
65 + return t0;
66 }
67 export const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
68
compiler/forget/src/__tests__/fixtures/compiler/gating-test-export-function.expect.md
+22 -2
@@ -28,7 +28,17 @@ function Bar_uncompiled(props) {
28 return <div>{props.bar}</div>;
29 }
30 function Bar_forget(props) {
31 - return <div>{props.bar}</div>;
31 + const $ = React.unstable_useMemoCache(2);
32 + const c_0 = $[0] !== props.bar;
33 + let t0;
34 + if (c_0) {
35 + t0 = <div>{props.bar}</div>;
36 + $[0] = props.bar;
37 + $[1] = t0;
38 + } else {
39 + t0 = $[1];
40 + }
41 + return t0;
42 }
43 export const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
44
@@ -41,7 +51,17 @@ function Foo_uncompiled(props) {
51 return <Foo>{props.bar}</Foo>;
52 }
53 function Foo_forget(props) {
44 - return <Foo>{props.bar}</Foo>;
54 + const $ = React.unstable_useMemoCache(2);
55 + const c_0 = $[0] !== props.bar;
56 + let t0;
57 + if (c_0) {
58 + t0 = <Foo>{props.bar}</Foo>;
59 + $[0] = props.bar;
60 + $[1] = t0;
61 + } else {
62 + t0 = $[1];
63 + }
64 + return t0;
65 }
66 export const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
67
compiler/forget/src/__tests__/fixtures/compiler/gating-test.expect.md
+22 -2
@@ -28,7 +28,17 @@ function Bar_uncompiled(props) {
28 return <div>{props.bar}</div>;
29 }
30 function Bar_forget(props) {
31 - return <div>{props.bar}</div>;
31 + const $ = React.unstable_useMemoCache(2);
32 + const c_0 = $[0] !== props.bar;
33 + let t0;
34 + if (c_0) {
35 + t0 = <div>{props.bar}</div>;
36 + $[0] = props.bar;
37 + $[1] = t0;
38 + } else {
39 + t0 = $[1];
40 + }
41 + return t0;
42 }
43 const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
44
@@ -41,7 +51,17 @@ function Foo_uncompiled(props) {
51 return <Foo>{props.bar}</Foo>;
52 }
53 function Foo_forget(props) {
44 - return <Foo>{props.bar}</Foo>;
54 + const $ = React.unstable_useMemoCache(2);
55 + const c_0 = $[0] !== props.bar;
56 + let t0;
57 + if (c_0) {
58 + t0 = <Foo>{props.bar}</Foo>;
59 + $[0] = props.bar;
60 + $[1] = t0;
61 + } else {
62 + t0 = $[1];
63 + }
64 + return t0;
65 }
66 const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
67
compiler/forget/src/__tests__/fixtures/compiler/hook-call.expect.md
+16 -7
@@ -26,7 +26,7 @@ function useFreeze() {}
26 function foo() {}
27
28 function Component(props) {
29 - const $ = React.unstable_useMemoCache(1);
29 + const $ = React.unstable_useMemoCache(3);
30 let t0;
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 t0 = [];
@@ -37,12 +37,21 @@ function Component(props) {
37 const x = t0;
38 const y = useFreeze(x);
39 foo(y, x);
40 - return (
41 - <Component>
42 - {x}
43 - {y}
44 - </Component>
45 - );
40 + const c_1 = $[1] !== y;
41 + let t1;
42 + if (c_1) {
43 + t1 = (
44 + <Component>
45 + {x}
46 + {y}
47 + </Component>
48 + );
49 + $[1] = y;
50 + $[2] = t1;
51 + } else {
52 + t1 = $[2];
53 + }
54 + return t1;
55 }
56
57 ```
compiler/forget/src/__tests__/fixtures/compiler/independent-across-if.expect.md
+13 -2
@@ -56,7 +56,7 @@ function Foo() {}
56 * return = <Foo a={a} b={b} />
57 */
58 function Component(props) {
59 - const $ = React.unstable_useMemoCache(5);
59 + const $ = React.unstable_useMemoCache(8);
60 const c_0 = $[0] !== props.a;
61 const c_1 = $[1] !== props.b;
62 const c_2 = $[2] !== props.c;
@@ -78,7 +78,18 @@ function Component(props) {
78 a = $[3];
79 b = $[4];
80 }
81 - return <Foo a={a} b={b}></Foo>;
81 + const c_5 = $[5] !== a;
82 + const c_6 = $[6] !== b;
83 + let t0;
84 + if (c_5 || c_6) {
85 + t0 = <Foo a={a} b={b}></Foo>;
86 + $[5] = a;
87 + $[6] = b;
88 + $[7] = t0;
89 + } else {
90 + t0 = $[7];
91 + }
92 + return t0;
93 }
94
95 ```
compiler/forget/src/__tests__/fixtures/compiler/independent.expect.md
+13 -2
@@ -38,7 +38,7 @@ function Foo() {}
38 * return = <Foo a={a} b={b} />
39 */
40 function Component(props) {
41 - const $ = React.unstable_useMemoCache(4);
41 + const $ = React.unstable_useMemoCache(7);
42 const c_0 = $[0] !== props.a;
43 let t0;
44 if (c_0) {
@@ -59,7 +59,18 @@ function Component(props) {
59 t1 = $[3];
60 }
61 const b = t1;
62 - return <Foo a={a} b={b}></Foo>;
62 + const c_4 = $[4] !== a;
63 + const c_5 = $[5] !== b;
64 + let t2;
65 + if (c_4 || c_5) {
66 + t2 = <Foo a={a} b={b}></Foo>;
67 + $[4] = a;
68 + $[5] = b;
69 + $[6] = t2;
70 + } else {
71 + t2 = $[6];
72 + }
73 + return t2;
74 }
75
76 function compute() {}
compiler/forget/src/__tests__/fixtures/compiler/interdependent-across-if.expect.md
+13 -2
@@ -45,7 +45,7 @@ function Foo() {}
45 * return = <Foo a={a} b={b} />
46 */
47 function Component(props) {
48 - const $ = React.unstable_useMemoCache(5);
48 + const $ = React.unstable_useMemoCache(8);
49 const c_0 = $[0] !== props.a;
50 const c_1 = $[1] !== props.b;
51 const c_2 = $[2] !== props.c;
@@ -66,7 +66,18 @@ function Component(props) {
66 a = $[3];
67 b = $[4];
68 }
69 - return <Foo a={a} b={b}></Foo>;
69 + const c_5 = $[5] !== a;
70 + const c_6 = $[6] !== b;
71 + let t0;
72 + if (c_5 || c_6) {
73 + t0 = <Foo a={a} b={b}></Foo>;
74 + $[5] = a;
75 + $[6] = b;
76 + $[7] = t0;
77 + } else {
78 + t0 = $[7];
79 + }
80 + return t0;
81 }
82
83 ```
compiler/forget/src/__tests__/fixtures/compiler/interdependent.expect.md
+13 -2
@@ -37,7 +37,7 @@ function Foo() {}
37 * return = <Foo a={a} b={b} />
38 */
39 function Component(props) {
40 - const $ = React.unstable_useMemoCache(4);
40 + const $ = React.unstable_useMemoCache(7);
41 const c_0 = $[0] !== props.a;
42 const c_1 = $[1] !== props.b;
43 let a;
@@ -54,7 +54,18 @@ function Component(props) {
54 a = $[2];
55 b = $[3];
56 }
57 - return <Foo a={a} b={b}></Foo>;
57 + const c_4 = $[4] !== a;
58 + const c_5 = $[5] !== b;
59 + let t0;
60 + if (c_4 || c_5) {
61 + t0 = <Foo a={a} b={b}></Foo>;
62 + $[4] = a;
63 + $[5] = b;
64 + $[6] = t0;
65 + } else {
66 + t0 = $[6];
67 + }
68 + return t0;
69 }
70
71 function compute() {}
compiler/forget/src/__tests__/fixtures/compiler/jsx-fragment.expect.md
+30 -6
@@ -19,12 +19,36 @@ function Foo(props) {
19
20 ```javascript
21 function Foo(props) {
22 - return (
23 - <>
24 - Hello {props.greeting}
25 - {<div>{<>Text</>}</div>}
26 - </>
27 - );
22 + const $ = React.unstable_useMemoCache(4);
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = <>Text</>;
26 + $[0] = t0;
27 + } else {
28 + t0 = $[0];
29 + }
30 + let t1;
31 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
32 + t1 = <div>{t0}</div>;
33 + $[1] = t1;
34 + } else {
35 + t1 = $[1];
36 + }
37 + const c_2 = $[2] !== props.greeting;
38 + let t2;
39 + if (c_2) {
40 + t2 = (
41 + <>
42 + Hello {props.greeting}
43 + {t1}
44 + </>
45 + );
46 + $[2] = props.greeting;
47 + $[3] = t2;
48 + } else {
49 + t2 = $[3];
50 + }
51 + return t2;
52 }
53
54 ```
compiler/forget/src/__tests__/fixtures/compiler/jsx-spread.expect.md
+13 -2
@@ -14,7 +14,7 @@ function Component(props) {
14
15 ```javascript
16 function Component(props) {
17 - const $ = React.unstable_useMemoCache(2);
17 + const $ = React.unstable_useMemoCache(5);
18
19 const t0 = props.cond ? props.foo : props.bar;
20 const c_0 = $[0] !== t0;
@@ -26,7 +26,18 @@ function Component(props) {
26 } else {
27 t1 = $[1];
28 }
29 - return <Component {...props} {...t1}></Component>;
29 + const c_2 = $[2] !== props;
30 + const c_3 = $[3] !== t1;
31 + let t2;
32 + if (c_2 || c_3) {
33 + t2 = <Component {...props} {...t1}></Component>;
34 + $[2] = props;
35 + $[3] = t1;
36 + $[4] = t2;
37 + } else {
38 + t2 = $[4];
39 + }
40 + return t2;
41 }
42
43 ```
compiler/forget/src/__tests__/fixtures/compiler/overlapping-scopes-shadowing-within-block.expect.md
+11 -3
@@ -21,7 +21,7 @@ function foo(a, b, c) {
21
22 ```javascript
23 function foo(a, b, c) {
24 - const $ = React.unstable_useMemoCache(7);
24 + const $ = React.unstable_useMemoCache(9);
25 const c_0 = $[0] !== a;
26 const c_1 = $[1] !== b;
27 const c_2 = $[2] !== c;
@@ -43,8 +43,16 @@ function foo(a, b, c) {
43 } else {
44 y = $[6];
45 }
46 -
47 - x.push(<div>{y}</div>);
46 + const c_7 = $[7] !== y;
47 + let t0;
48 + if (c_7) {
49 + t0 = <div>{y}</div>;
50 + $[7] = y;
51 + $[8] = t0;
52 + } else {
53 + t0 = $[8];
54 + }
55 + x.push(t0);
56 }
57 $[0] = a;
58 $[1] = b;
compiler/forget/src/__tests__/fixtures/compiler/property-assignment.expect.md
+13 -2
@@ -17,7 +17,7 @@ function Component(props) {
17
18 ```javascript
19 function Component(props) {
20 - const $ = React.unstable_useMemoCache(3);
20 + const $ = React.unstable_useMemoCache(6);
21 const c_0 = $[0] !== props.p0;
22 let x;
23 let child;
@@ -35,7 +35,18 @@ function Component(props) {
35 x = $[1];
36 child = $[2];
37 }
38 - return <Component data={x}>{child}</Component>;
38 + const c_3 = $[3] !== x;
39 + const c_4 = $[4] !== child;
40 + let t0;
41 + if (c_3 || c_4) {
42 + t0 = <Component data={x}>{child}</Component>;
43 + $[3] = x;
44 + $[4] = child;
45 + $[5] = t0;
46 + } else {
47 + t0 = $[5];
48 + }
49 + return t0;
50 }
51
52 ```
compiler/forget/src/__tests__/fixtures/compiler/reactive-scopes-if.expect.md
+11 -2
@@ -20,7 +20,7 @@ function foo(a, b, c) {
20
21 ```javascript
22 function foo(a, b, c) {
23 - const $ = React.unstable_useMemoCache(6);
23 + const $ = React.unstable_useMemoCache(8);
24 const c_0 = $[0] !== a;
25 const c_1 = $[1] !== b;
26 const c_2 = $[2] !== c;
@@ -38,7 +38,16 @@ function foo(a, b, c) {
38 } else {
39 y = $[5];
40 }
41 - x.push(<div>{y}</div>);
41 + const c_6 = $[6] !== y;
42 + let t0;
43 + if (c_6) {
44 + t0 = <div>{y}</div>;
45 + $[6] = y;
46 + $[7] = t0;
47 + } else {
48 + t0 = $[7];
49 + }
50 + x.push(t0);
51 } else {
52 x.push(c);
53 }
compiler/forget/src/__tests__/fixtures/compiler/reactive-scopes.expect.md
+11 -2
@@ -19,7 +19,7 @@ function f(a, b) {
19
20 ```javascript
21 function f(a, b) {
22 - const $ = React.unstable_useMemoCache(3);
22 + const $ = React.unstable_useMemoCache(5);
23 const c_0 = $[0] !== a.length;
24 const c_1 = $[1] !== b;
25 let x;
@@ -36,7 +36,16 @@ function f(a, b) {
36 } else {
37 x = $[2];
38 }
39 - return <div>{x}</div>;
39 + const c_3 = $[3] !== x;
40 + let t0;
41 + if (c_3) {
42 + t0 = <div>{x}</div>;
43 + $[3] = x;
44 + $[4] = t0;
45 + } else {
46 + t0 = $[4];
47 + }
48 + return t0;
49 }
50
51 ```
compiler/forget/src/__tests__/fixtures/compiler/reassignment-conditional.expect.md
+13 -2
@@ -23,7 +23,7 @@ function Component(props) {
23
24 ```javascript
25 function Component(props) {
26 - const $ = React.unstable_useMemoCache(3);
26 + const $ = React.unstable_useMemoCache(6);
27 const c_0 = $[0] !== props.p0;
28 let x;
29 if (c_0) {
@@ -47,7 +47,18 @@ function Component(props) {
47 }
48
49 y.push(props.p2);
50 - return <Component x={x} y={y}></Component>;
50 + const c_3 = $[3] !== x;
51 + const c_4 = $[4] !== y;
52 + let t1;
53 + if (c_3 || c_4) {
54 + t1 = <Component x={x} y={y}></Component>;
55 + $[3] = x;
56 + $[4] = y;
57 + $[5] = t1;
58 + } else {
59 + t1 = $[5];
60 + }
61 + return t1;
62 }
63
64 ```
compiler/forget/src/__tests__/fixtures/compiler/reassignment-separate-scopes.expect.md
+38 -19
@@ -34,7 +34,7 @@ function foo(a, b, c) {
34
35 ```javascript
36 function foo(a, b, c) {
37 - const $ = React.unstable_useMemoCache(6);
37 + const $ = React.unstable_useMemoCache(11);
38 const c_0 = $[0] !== a;
39 let x;
40 if (c_0) {
@@ -47,39 +47,58 @@ function foo(a, b, c) {
47 } else {
48 x = $[1];
49 }
50 -
51 - const y = <div>{x}</div>;
50 + const c_2 = $[2] !== x;
51 + let t0;
52 + if (c_2) {
53 + t0 = <div>{x}</div>;
54 + $[2] = x;
55 + $[3] = t0;
56 + } else {
57 + t0 = $[3];
58 + }
59 + const y = t0;
60 bb3: switch (b) {
61 case 0: {
54 - const c_2 = $[2] !== b;
55 - if (c_2) {
62 + const c_4 = $[4] !== b;
63 + if (c_4) {
64 x = [];
65 x.push(b);
58 - $[2] = b;
59 - $[3] = x;
66 + $[4] = b;
67 + $[5] = x;
68 } else {
61 - x = $[3];
69 + x = $[5];
70 }
71 break bb3;
72 }
73 default: {
66 - const c_4 = $[4] !== c;
67 - if (c_4) {
74 + const c_6 = $[6] !== c;
75 + if (c_6) {
76 x = [];
77 x.push(c);
70 - $[4] = c;
71 - $[5] = x;
78 + $[6] = c;
79 + $[7] = x;
80 } else {
73 - x = $[5];
81 + x = $[7];
82 }
83 }
84 }
77 - return (
78 - <div>
79 - {y}
80 - {x}
81 - </div>
82 - );
85 + const c_8 = $[8] !== y;
86 + const c_9 = $[9] !== x;
87 + let t1;
88 + if (c_8 || c_9) {
89 + t1 = (
90 + <div>
91 + {y}
92 + {x}
93 + </div>
94 + );
95 + $[8] = y;
96 + $[9] = x;
97 + $[10] = t1;
98 + } else {
99 + t1 = $[10];
100 + }
101 + return t1;
102 }
103
104 ```
compiler/forget/src/__tests__/fixtures/compiler/reassignment.expect.md
+13 -2
@@ -21,7 +21,7 @@ function Component(props) {
21
22 ```javascript
23 function Component(props) {
24 - const $ = React.unstable_useMemoCache(5);
24 + const $ = React.unstable_useMemoCache(8);
25 const c_0 = $[0] !== props.p0;
26 const c_1 = $[1] !== props.p1;
27 let x;
@@ -48,7 +48,18 @@ function Component(props) {
48 x = $[2];
49 y = $[3];
50 }
51 - return <Component x={x} y={y}></Component>;
51 + const c_5 = $[5] !== x;
52 + const c_6 = $[6] !== y;
53 + let t1;
54 + if (c_5 || c_6) {
55 + t1 = <Component x={x} y={y}></Component>;
56 + $[5] = x;
57 + $[6] = y;
58 + $[7] = t1;
59 + } else {
60 + t1 = $[7];
61 + }
62 + return t1;
63 }
64
65 ```
compiler/forget/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md
+58 -27
@@ -46,7 +46,7 @@ function foo(props) {
46 // note: comments are for the ideal scopes, not what is currently
47 // emitted
48 function foo(props) {
49 - const $ = React.unstable_useMemoCache(7);
49 + const $ = React.unstable_useMemoCache(16);
50 const c_0 = $[0] !== props.a;
51 let x;
52 if (c_0) {
@@ -57,39 +57,70 @@ function foo(props) {
57 } else {
58 x = $[1];
59 }
60 -
61 - const header = props.showHeader ? <div>{x}</div> : null;
62 - const c_2 = $[2] !== x;
63 - const c_3 = $[3] !== props.b;
64 - const c_4 = $[4] !== props.c;
60 + const c_2 = $[2] !== props.showHeader;
61 + const c_3 = $[3] !== x;
62 + let t0;
63 + if (c_2 || c_3) {
64 + t0 = props.showHeader ? <div>{x}</div> : null;
65 + $[2] = props.showHeader;
66 + $[3] = x;
67 + $[4] = t0;
68 + } else {
69 + t0 = $[4];
70 + }
71 + const header = t0;
72 + const c_5 = $[5] !== x;
73 + const c_6 = $[6] !== props.b;
74 + const c_7 = $[7] !== props.c;
75 let y;
66 - if (c_2 || c_3 || c_4) {
76 + if (c_5 || c_6 || c_7) {
77 y = [x];
78 x = [];
79 y.push(props.b);
80 x.push(props.c);
71 - $[2] = x;
72 - $[3] = props.b;
73 - $[4] = props.c;
74 - $[5] = y;
75 - $[6] = x;
81 + $[5] = x;
82 + $[6] = props.b;
83 + $[7] = props.c;
84 + $[8] = y;
85 + $[9] = x;
86 } else {
77 - y = $[5];
78 - x = $[6];
87 + y = $[8];
88 + x = $[9];
89 }
80 -
81 - const content = (
82 - <div>
83 - {x}
84 - {y}
85 - </div>
86 - );
87 - return (
88 - <>
89 - {header}
90 - {content}
91 - </>
92 - );
90 + const c_10 = $[10] !== x;
91 + const c_11 = $[11] !== y;
92 + let t1;
93 + if (c_10 || c_11) {
94 + t1 = (
95 + <div>
96 + {x}
97 + {y}
98 + </div>
99 + );
100 + $[10] = x;
101 + $[11] = y;
102 + $[12] = t1;
103 + } else {
104 + t1 = $[12];
105 + }
106 + const content = t1;
107 + const c_13 = $[13] !== header;
108 + const c_14 = $[14] !== content;
109 + let t2;
110 + if (c_13 || c_14) {
111 + t2 = (
112 + <>
113 + {header}
114 + {content}
115 + </>
116 + );
117 + $[13] = header;
118 + $[14] = content;
119 + $[15] = t2;
120 + } else {
121 + t2 = $[15];
122 + }
123 + return t2;
124 }
125
126 ```
compiler/forget/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare.expect.md
+55 -26
@@ -46,7 +46,7 @@ function foo(props) {
46 // note: comments are for the ideal scopes, not what is currently
47 // emitted
48 function foo(props) {
49 - const $ = React.unstable_useMemoCache(7);
49 + const $ = React.unstable_useMemoCache(15);
50 const c_0 = $[0] !== props.a;
51 let x;
52 if (c_0) {
@@ -57,39 +57,68 @@ function foo(props) {
57 } else {
58 x = $[1];
59 }
60 -
61 - const header = <div>{x}</div>;
60 const c_2 = $[2] !== x;
63 - const c_3 = $[3] !== props.b;
64 - const c_4 = $[4] !== props.c;
61 + let t0;
62 + if (c_2) {
63 + t0 = <div>{x}</div>;
64 + $[2] = x;
65 + $[3] = t0;
66 + } else {
67 + t0 = $[3];
68 + }
69 + const header = t0;
70 + const c_4 = $[4] !== x;
71 + const c_5 = $[5] !== props.b;
72 + const c_6 = $[6] !== props.c;
73 let y;
66 - if (c_2 || c_3 || c_4) {
74 + if (c_4 || c_5 || c_6) {
75 y = [x];
76 x = [];
77 y.push(props.b);
78 x.push(props.c);
71 - $[2] = x;
72 - $[3] = props.b;
73 - $[4] = props.c;
74 - $[5] = y;
75 - $[6] = x;
79 + $[4] = x;
80 + $[5] = props.b;
81 + $[6] = props.c;
82 + $[7] = y;
83 + $[8] = x;
84 } else {
77 - y = $[5];
78 - x = $[6];
85 + y = $[7];
86 + x = $[8];
87 }
80 -
81 - const content = (
82 - <div>
83 - {x}
84 - {y}
85 - </div>
86 - );
87 - return (
88 - <>
89 - {header}
90 - {content}
91 - </>
92 - );
88 + const c_9 = $[9] !== x;
89 + const c_10 = $[10] !== y;
90 + let t1;
91 + if (c_9 || c_10) {
92 + t1 = (
93 + <div>
94 + {x}
95 + {y}
96 + </div>
97 + );
98 + $[9] = x;
99 + $[10] = y;
100 + $[11] = t1;
101 + } else {
102 + t1 = $[11];
103 + }
104 + const content = t1;
105 + const c_12 = $[12] !== header;
106 + const c_13 = $[13] !== content;
107 + let t2;
108 + if (c_12 || c_13) {
109 + t2 = (
110 + <>
111 + {header}
112 + {content}
113 + </>
114 + );
115 + $[12] = header;
116 + $[13] = content;
117 + $[14] = t2;
118 + } else {
119 + t2 = $[14];
120 + }
121 + return t2;
122 }
123
124 ```
compiler/forget/src/__tests__/fixtures/compiler/ssa-call-jsx-2.expect.md
+9 -2
@@ -25,7 +25,7 @@ function Component(props) {
25 function foo() {}
26
27 function Component(props) {
28 - const $ = React.unstable_useMemoCache(2);
28 + const $ = React.unstable_useMemoCache(3);
29 let a;
30 let b;
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -42,7 +42,14 @@ function Component(props) {
42 a = $[0];
43 b = $[1];
44 }
45 - return <div a={a} b={b}></div>;
45 + let t0;
46 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
47 + t0 = <div a={a} b={b}></div>;
48 + $[2] = t0;
49 + } else {
50 + t0 = $[2];
51 + }
52 + return t0;
53 }
54
55 ```
compiler/forget/src/__tests__/fixtures/compiler/ssa-call-jsx.expect.md
+9 -2
@@ -21,7 +21,7 @@ function Component(props) {
21 function foo() {}
22
23 function Component(props) {
24 - const $ = React.unstable_useMemoCache(2);
24 + const $ = React.unstable_useMemoCache(3);
25 let a;
26 let b;
27 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -36,7 +36,14 @@ function Component(props) {
36 a = $[0];
37 b = $[1];
38 }
39 - return <div a={a} b={b}></div>;
39 + let t0;
40 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
41 + t0 = <div a={a} b={b}></div>;
42 + $[2] = t0;
43 + } else {
44 + t0 = $[2];
45 + }
46 + return t0;
47 }
48
49 ```
compiler/forget/src/__tests__/fixtures/compiler/ssa-leave-case.expect.md
+18 -7
@@ -23,7 +23,7 @@ function Component(props) {
23
24 ```javascript
25 function Component(props) {
26 - const $ = React.unstable_useMemoCache(3);
26 + const $ = React.unstable_useMemoCache(6);
27 const c_0 = $[0] !== props;
28 let x;
29 let y;
@@ -41,12 +41,23 @@ function Component(props) {
41 x = $[1];
42 y = $[2];
43 }
44 - return (
45 - <Component>
46 - {x}
47 - {y}
48 - </Component>
49 - );
44 + const c_3 = $[3] !== x;
45 + const c_4 = $[4] !== y;
46 + let t0;
47 + if (c_3 || c_4) {
48 + t0 = (
49 + <Component>
50 + {x}
51 + {y}
52 + </Component>
53 + );
54 + $[3] = x;
55 + $[4] = y;
56 + $[5] = t0;
57 + } else {
58 + t0 = $[5];
59 + }
60 + return t0;
61 }
62
63 ```
compiler/forget/src/__tests__/fixtures/compiler/switch-non-final-default.expect.md
+23 -4
@@ -32,7 +32,7 @@ function Component(props) {
32
33 ```javascript
34 function Component(props) {
35 - const $ = React.unstable_useMemoCache(4);
35 + const $ = React.unstable_useMemoCache(9);
36 const c_0 = $[0] !== props;
37 let x;
38 let y;
@@ -69,10 +69,29 @@ function Component(props) {
69 x = $[1];
70 y = $[2];
71 }
72 -
73 - const child = <Component data={x}></Component>;
72 + const c_4 = $[4] !== x;
73 + let t1;
74 + if (c_4) {
75 + t1 = <Component data={x}></Component>;
76 + $[4] = x;
77 + $[5] = t1;
78 + } else {
79 + t1 = $[5];
80 + }
81 + const child = t1;
82 y.push(props.p4);
75 - return <Component data={y}>{child}</Component>;
83 + const c_6 = $[6] !== y;
84 + const c_7 = $[7] !== child;
85 + let t2;
86 + if (c_6 || c_7) {
87 + t2 = <Component data={y}>{child}</Component>;
88 + $[6] = y;
89 + $[7] = child;
90 + $[8] = t2;
91 + } else {
92 + t2 = $[8];
93 + }
94 + return t2;
95 }
96
97 ```
compiler/forget/src/__tests__/fixtures/compiler/switch.expect.md
+23 -4
@@ -27,7 +27,7 @@ function Component(props) {
27
28 ```javascript
29 function Component(props) {
30 - const $ = React.unstable_useMemoCache(3);
30 + const $ = React.unstable_useMemoCache(8);
31 const c_0 = $[0] !== props;
32 let x;
33 let y;
@@ -50,10 +50,29 @@ function Component(props) {
50 x = $[1];
51 y = $[2];
52 }
53 -
54 - const child = <Component data={x}></Component>;
53 + const c_3 = $[3] !== x;
54 + let t0;
55 + if (c_3) {
56 + t0 = <Component data={x}></Component>;
57 + $[3] = x;
58 + $[4] = t0;
59 + } else {
60 + t0 = $[4];
61 + }
62 + const child = t0;
63 y.push(props.p4);
56 - return <Component data={y}>{child}</Component>;
64 + const c_5 = $[5] !== y;
65 + const c_6 = $[6] !== child;
66 + let t1;
67 + if (c_5 || c_6) {
68 + t1 = <Component data={y}>{child}</Component>;
69 + $[5] = y;
70 + $[6] = child;
71 + $[7] = t1;
72 + } else {
73 + t1 = $[7];
74 + }
75 + return t1;
76 }
77
78 ```
compiler/forget/src/__tests__/fixtures/compiler/temporary-at-start-of-value-block.expect.md
+11 -1
@@ -14,7 +14,17 @@ function component(props) {
14
15 ```javascript
16 function component(props) {
17 - const x = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;
17 + const $ = React.unstable_useMemoCache(2);
18 + const c_0 = $[0] !== props;
19 + let t0;
20 + if (c_0) {
21 + t0 = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;
22 + $[0] = props;
23 + $[1] = t0;
24 + } else {
25 + t0 = $[1];
26 + }
27 + const x = t0;
28 return x;
29 }
30
compiler/forget/src/__tests__/fixtures/compiler/timers.expect.md
+13 -6
@@ -19,7 +19,7 @@ function Component(props) {
19
20 ```javascript
21 function Component(props) {
22 - const $ = React.unstable_useMemoCache(1);
22 + const $ = React.unstable_useMemoCache(2);
23 const start = performance.now();
24 let t0;
25 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -30,11 +30,18 @@ function Component(props) {
30 }
31 const now = t0;
32 const time = performance.now() - start;
33 - return (
34 - <div>
35 - rendering took {time} at {now}
36 - </div>
37 - );
33 + let t1;
34 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
35 + t1 = (
36 + <div>
37 + rendering took {time} at {now}
38 + </div>
39 + );
40 + $[1] = t1;
41 + } else {
42 + t1 = $[1];
43 + }
44 + return t1;
45 }
46
47 ```
compiler/forget/src/__tests__/fixtures/compiler/use-callback-simple.expect.md
+11 -2
@@ -15,7 +15,7 @@ function component() {
15
16 ```javascript
17 function component() {
18 - const $ = React.unstable_useMemoCache(3);
18 + const $ = React.unstable_useMemoCache(5);
19 const [count, setCount] = useState(0);
20 const c_0 = $[0] !== setCount;
21 const c_1 = $[1] !== count;
@@ -29,7 +29,16 @@ function component() {
29 t0 = $[2];
30 }
31 const increment = t0;
32 - return <Foo onClick={increment}></Foo>;
32 + const c_3 = $[3] !== increment;
33 + let t1;
34 + if (c_3) {
35 + t1 = <Foo onClick={increment}></Foo>;
36 + $[3] = increment;
37 + $[4] = t1;
38 + } else {
39 + t1 = $[4];
40 + }
41 + return t1;
42 }
43
44 ```
compiler/forget/src/__tests__/fixtures/compiler/useMemo-simple.expect.md
+11 -2
@@ -13,7 +13,7 @@ function component(a) {
13
14 ```javascript
15 function component(a) {
16 - const $ = React.unstable_useMemoCache(2);
16 + const $ = React.unstable_useMemoCache(4);
17 const c_0 = $[0] !== a;
18 let t0;
19 if (c_0) {
@@ -24,7 +24,16 @@ function component(a) {
24 t0 = $[1];
25 }
26 const x = t0;
27 - return <Foo x={x}></Foo>;
27 + const c_2 = $[2] !== x;
28 + let t1;
29 + if (c_2) {
30 + t1 = <Foo x={x}></Foo>;
31 + $[2] = x;
32 + $[3] = t1;
33 + } else {
34 + t1 = $[3];
35 + }
36 + return t1;
37 }
38
39 ```
compiler/forget/src/__tests__/fixtures/disableMemoizeJsxElements/Component.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + const [name, setName] = useState(null);
7 + const onChange = function (e) {
8 + setName(e.target.value);
9 + };
10 + return (
11 + <form>
12 + <input onChange={onChange} value={name} />
13 + </form>
14 + );
15 +}
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +function Component(props) {
23 + const $ = React.unstable_useMemoCache(2);
24 + const [name, setName] = useState(null);
25 + const c_0 = $[0] !== setName;
26 + let t0;
27 + if (c_0) {
28 + t0 = function (e) {
29 + setName(e.target.value);
30 + };
31 + $[0] = setName;
32 + $[1] = t0;
33 + } else {
34 + t0 = $[1];
35 + }
36 + const onChange = t0;
37 + return <form>{<input onChange={onChange} value={name}></input>}</form>;
38 +}
39 +
40 +```
41 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/disableMemoizeJsxElements/Component.js new
+11
@@ -0,0 +1,11 @@
1 +function Component(props) {
2 + const [name, setName] = useState(null);
3 + const onChange = function (e) {
4 + setName(e.target.value);
5 + };
6 + return (
7 + <form>
8 + <input onChange={onChange} value={name} />
9 + </form>
10 + );
11 +}