@samitouri / QOS-React / commits / 23e0ce02a6
Fork 0

The library for web and native user interfaces.

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 +}