@samitouri / QOS-React / commits / ecb084c4b8

[ReactiveHIR] Infer reactive identifiers and promote temporaries

Messed up ghstack, this is a duplicate of #1093

mofeiZ committed Feb 3, 2023 at 14:52 UTC ecb084c4b8b0e7dddadf5fce73e194a8b58d3187
46 files changed +505 -344
compiler/forget/src/CompilerPipeline.ts
+8
@@ -27,6 +27,7 @@ import {
27 flattenReactiveLoops,
28 inferReactiveScopeVariables,
29 mergeOverlappingReactiveScopes,
30 + promoteUsedTemporaries,
31 propagateScopeDependencies,
32 pruneUnusedLabels,
33 pruneUnusedLValues,
@@ -128,6 +129,13 @@ export function* run(
129 value: reactiveFunction,
130 });
131
132 + promoteUsedTemporaries(reactiveFunction);
133 + yield log({
134 + kind: "reactive",
135 + name: "promoteUsedTemporaries",
136 + value: reactiveFunction,
137 + });
138 +
139 pruneUnusedLabels(reactiveFunction);
140 yield log({
141 kind: "reactive",
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+5 -2
@@ -185,8 +185,11 @@ function codegenReactiveScope(
185 firstOutputIndex = index;
186 }
187
188 - // TODO @josephsavona: ensure change and temp variables have non-conflicting names
189 - output.name ??= `t${index}`;
188 + invariant(
189 + output.name != null,
190 + "Expected identifier '@%s' to be named",
191 + output.id
192 + );
193
194 const name = convertIdentifier(output);
195 cx.declare(output);
compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts new
+127
@@ -0,0 +1,127 @@
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 +import {
9 + Identifier,
10 + ReactiveFunction,
11 + ReactiveInstruction,
12 + ReactiveScope,
13 +} from "../HIR/HIR";
14 +import {
15 + eachReactiveValueOperand,
16 + ReactiveFunctionVisitor,
17 + visitReactiveFunction,
18 +} from "./visitors";
19 +
20 +type IdentifierReactivity = Map<Identifier, boolean>;
21 +class Environment extends ReactiveFunctionVisitor<IdentifierReactivity> {
22 + override visitInstruction(
23 + instr: ReactiveInstruction,
24 + reactivityMap: IdentifierReactivity
25 + ) {
26 + this.traverseInstruction(instr, reactivityMap);
27 + const lval = instr.lvalue;
28 + if (lval == null || reactivityMap.get(lval.place.identifier) === true) {
29 + return;
30 + }
31 + const { value } = instr;
32 + let hasReactiveInput = false;
33 + for (const operand of eachReactiveValueOperand(value)) {
34 + // We currently treat free variables (from module or global scope) as
35 + // non-reactive. We may later want type information about specific
36 + // free variables, or a toggle `treatFreeVarsAsReactive`.
37 + if (reactivityMap.get(operand.identifier)) {
38 + hasReactiveInput = true;
39 + break;
40 + }
41 + }
42 + reactivityMap.set(lval.place.identifier, hasReactiveInput);
43 +
44 + if (hasReactiveInput) {
45 + // all mutating effects must also be marked as reactive
46 + for (const operand of eachReactiveValueOperand(value)) {
47 + if (operand.effect === "store" || operand.effect === "mutate") {
48 + // Explicitly compare to `false` here, since absence from the
49 + // map indicates a free variable
50 + // todo [@mofeiZ] add knowledge about free variables
51 + if (reactivityMap.get(operand.identifier) === false) {
52 + reactivityMap.set(operand.identifier, true);
53 + }
54 + }
55 + }
56 + }
57 + }
58 +}
59 +/**
60 + * Computes a map of {@link Place} -> reactivityMap. A Place is reactive if any
61 + * operant used in its construction is reactive. Sources of reactivity are
62 + * {@link ReactiveFunction.params} and HookCall return values (TODO).
63 + * Free values are currently not populated.
64 + *
65 + * This relies on alias analysis done by InferReactiveScopeVariables, which
66 + * creates reactive scopes for variables that mutate together. If one value
67 + * declared in a scope is Reactive, then the rest are marked as reactive as
68 + * well.
69 + * e.g.
70 + * ```javascript
71 + * function foo(props) {
72 + * let x = {};
73 + * let y = [];
74 + * x.y = y;
75 + * y.push(props.a)
76 + * // references to x are reactive here
77 + * }
78 + * ```
79 + * This an overestimate when two identifiers have overlapping scope, but
80 + * one is not actually reactive. However, since the same ReactiveBlock now
81 + * produces both identifiers, they are effectively both effective (i.e.
82 + * object creation is not stable)
83 + * e.g.
84 + * ```javascript
85 + * function bar(props) {
86 + * let x = {};
87 + * let y = [];
88 + * mutate1(x, props);
89 + * mutate2(y);
90 + * }
91 + * ```
92 + */
93 +export function inferReactiveIdentifiers(
94 + fn: ReactiveFunction
95 +): Set<Identifier> {
96 + const visitor = new Environment();
97 + const reactivityMap: IdentifierReactivity = new Map();
98 + for (const param of fn.params) {
99 + reactivityMap.set(param.identifier, true);
100 + }
101 + const actuallyReactiveScopes = new Set<ReactiveScope>();
102 + let prevScopesSize = -1;
103 +
104 + // TODO(mofeiZ): avoid fixpoint iteration by keeping a map of identifiers
105 + // read by a ReactiveScope (that are produced outside of it)
106 + while (actuallyReactiveScopes.size > prevScopesSize) {
107 + prevScopesSize = actuallyReactiveScopes.size;
108 + visitReactiveFunction(fn, visitor, reactivityMap);
109 +
110 + for (const [id, value] of reactivityMap) {
111 + const { scope } = id;
112 + if (value && scope != null) {
113 + actuallyReactiveScopes.add(scope);
114 + }
115 + }
116 + for (const [id, _] of reactivityMap) {
117 + if (id.scope && actuallyReactiveScopes.has(id.scope)) {
118 + reactivityMap.set(id, true);
119 + }
120 + }
121 + }
122 + const result = new Set<Identifier>();
123 + reactivityMap.forEach((isReactive, id) => {
124 + if (isReactive) result.add(id);
125 + });
126 + return result;
127 +}
compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts new
+37
@@ -0,0 +1,37 @@
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 +import { ReactiveFunction, ReactiveScopeBlock } from "../HIR/HIR";
9 +import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
10 +
11 +type VisitorState = {
12 + nextId: number;
13 +};
14 +class Visitor extends ReactiveFunctionVisitor<VisitorState> {
15 + override visitScope(block: ReactiveScopeBlock, state: VisitorState) {
16 + this.traverseScope(block, state);
17 + for (const dep of block.scope.dependencies) {
18 + const { identifier } = dep.place;
19 + if (identifier.name == null) {
20 + identifier.name = `t${state.nextId++}`;
21 + }
22 + }
23 + // This is technically optional. We could prune ReactiveScopes
24 + // whose outputs are not used in another computation or return
25 + // value.
26 + // Many of our current test fixtures do not return a value, so
27 + // it is better for now to promote (and memoize) every output.
28 + for (const identifier of block.scope.outputs) {
29 + if (identifier.name == null) {
30 + identifier.name = `t${state.nextId++}`;
31 + }
32 + }
33 + }
34 +}
35 +export function promoteUsedTemporaries(fn: ReactiveFunction) {
36 + visitReactiveFunction(fn, new Visitor(), { nextId: 0 });
37 +}
compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+18 -11
@@ -9,7 +9,6 @@ import {
9 Identifier,
10 InstructionId,
11 InstructionKind,
12 - isPrimitiveType,
12 LValue,
13 makeInstructionId,
14 Place,
@@ -22,6 +21,7 @@ import {
21 } from "../HIR/HIR";
22 import { eachInstructionValueOperand } from "../HIR/visitors";
23 import { assertExhaustive } from "../Utils/utils";
24 +import { inferReactiveIdentifiers } from "./InferReactiveIdentifiers";
25 import { eachReactiveValueOperand } from "./visitors";
26
27 /**
@@ -31,7 +31,7 @@ import { eachReactiveValueOperand } from "./visitors";
31 * their direct dependencies and those of their child scopes.
32 */
33 export function propagateScopeDependencies(fn: ReactiveFunction): void {
34 - const context = new Context();
34 + const context = new Context(inferReactiveIdentifiers(fn));
35 if (fn.id !== null) {
36 context.declare(fn.id, { kind: DeclKind.Const, id: makeInstructionId(0) });
37 }
@@ -57,9 +57,16 @@ type Scopes = Array<ReactiveScope>;
57 class Context {
58 #declarations: DeclMap = new Map();
59 #dependencies: Set<ReactiveScopeDependency> = new Set();
60 + #reactiveIdentifiers: Set<Identifier>;
61 + // Produces a de-duplicated mapping of Id -> ReactiveScopeDependency
62 + // This helps with.. temporaries that are created only for property loads
63 + // but can be generalized to all non-allocating temporaries
64 #properties: Map<Identifier, ReactiveScopeDependency> = new Map();
65 #scopes: Scopes = [];
66
67 + constructor(reactiveIdentifiers: Set<Identifier>) {
68 + this.#reactiveIdentifiers = reactiveIdentifiers;
69 + }
70 enter(scope: ReactiveScope, fn: () => void): Set<ReactiveScopeDependency> {
71 const previousDependencies = this.#dependencies;
72 const scopedDependencies = new Set<ReactiveScopeDependency>();
@@ -97,6 +104,10 @@ class Context {
104 return this.#scopes.at(-1)!;
105 }
106
107 + isReactive(id: Identifier): boolean {
108 + return this.#reactiveIdentifiers.has(id);
109 + }
110 +
111 visitOperand(place: Place): void {
112 this.visitDependency({ place, path: null });
113 }
@@ -133,6 +144,8 @@ class Context {
144 }
145
146 const decl = this.#declarations.get(maybeDependency.place.identifier);
147 + // if decl is undefined here, then this is a free var
148 + // (all other decls e.g. `let x;` should be initialized in BuildHIR)
149
150 // Any value used after its defining scope has concluded must be added as an
151 // output of its defining scope. Regardless of whether its a const or not,
@@ -323,19 +336,13 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void {
336 const { lvalue } = instr;
337 visitInstructionValue(context, instr.value, lvalue);
338 if (lvalue !== null && lvalue.kind !== InstructionKind.Reassign) {
326 - const range = lvalue.place.identifier.mutableRange;
339 // TODO: only assign Const if the value is never reassigned
328 - const kind =
329 - range.end === range.start + 1
330 - ? valueKind(lvalue.place.identifier)
331 - : DeclKind.Dynamic;
340 + const kind = context.isReactive(lvalue.place.identifier)
341 + ? DeclKind.Dynamic
342 + : DeclKind.Const;
343 context.declare(lvalue.place.identifier, {
344 kind,
345 id: lvalue.place.identifier.mutableRange.start,
346 });
347 }
348 }
338 -
339 -function valueKind(id: Identifier): DeclKind {
340 - return isPrimitiveType(id) ? DeclKind.Const : DeclKind.Dynamic;
341 -}
compiler/forget/src/ReactiveScopes/index.ts
+1
@@ -13,6 +13,7 @@ export { flattenReactiveLoops } from "./FlattenReactiveLoops";
13 export { inferReactiveScopeVariables } from "./InferReactiveScopeVariables";
14 export { mergeOverlappingReactiveScopes } from "./MergeOverlappingReactiveScopes";
15 export { printReactiveFunction } from "./PrintReactiveFunction";
16 +export { promoteUsedTemporaries } from "./PromoteUsedTemporaries";
17 export { propagateScopeDependencies } from "./PropagateScopeDependencies";
18 export { pruneTemporaryLValues as pruneUnusedLValues } from "./PruneTemporaryLValues";
19 export { pruneUnusedLabels } from "./PruneUnusedLabels";
compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md
+6 -10
@@ -25,25 +25,21 @@ function component() {
25 } else {
26 z = $[0];
27 }
28 - const c_1 = $[1] !== z;
28 let y;
30 - if (c_1) {
29 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
30 y = {};
31 y.z = z;
33 - $[1] = z;
34 - $[2] = y;
32 + $[1] = y;
33 } else {
36 - y = $[2];
34 + y = $[1];
35 }
38 - const c_3 = $[3] !== y;
36 let x;
40 - if (c_3) {
37 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
38 x = {};
39 x.y = y;
43 - $[3] = y;
44 - $[4] = x;
40 + $[2] = x;
41 } else {
46 - x = $[4];
42 + x = $[2];
43 }
44 return x;
45 }
compiler/forget/src/__tests__/fixtures/hir/call.expect.md
+6 -10
@@ -36,18 +36,14 @@ function Component(props) {
36 a = $[0];
37 b = $[1];
38 }
39 - const c_2 = $[2] !== a;
40 - const c_3 = $[3] !== b;
41 - let t4;
42 - if (c_2 || c_3) {
43 - t4 = <div a={a} b={b}></div>;
44 - $[2] = a;
45 - $[3] = b;
46 - $[4] = t4;
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 {
48 - t4 = $[4];
44 + t0 = $[2];
45 }
50 - return t4;
46 + return t0;
47 }
48
49 ```
compiler/forget/src/__tests__/fixtures/hir/capture-param-mutate.expect.md
+5 -5
@@ -48,9 +48,9 @@ function getNativeLogFunction(level) {
48 function getNativeLogFunction(level) {
49 const $ = React.useMemoCache();
50 const c_0 = $[0] !== level;
51 - let t1;
51 + let t0;
52 if (c_0) {
53 - t1 = function () {
53 + t0 = function () {
54 let str;
55 if (arguments.length === 1 && typeof arguments[0] === "string") {
56 str = arguments[0];
@@ -86,11 +86,11 @@ function getNativeLogFunction(level) {
86 global.nativeLoggingHook(str, logLevel);
87 };
88 $[0] = level;
89 - $[1] = t1;
89 + $[1] = t0;
90 } else {
91 - t1 = $[1];
91 + t0 = $[1];
92 }
93 - return t1;
93 + return t0;
94 }
95
96 ```
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md
+7 -7
@@ -18,19 +18,19 @@ function component(a) {
18 function component(a) {
19 const $ = React.useMemoCache();
20 const c_0 = $[0] !== a;
21 - let t1;
21 + let t0;
22 if (c_0) {
23 - t1 = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = t1;
25 + $[1] = t0;
26 } else {
27 - t1 = $[1];
27 + t0 = $[1];
28 }
29 - const c_2 = $[2] !== t1;
29 + const c_2 = $[2] !== t0;
30 let z;
31 if (c_2) {
32 - z = { a: t1 };
33 - $[2] = t1;
32 + z = { a: t0 };
33 + $[2] = t0;
34 $[3] = z;
35 } else {
36 z = $[3];
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md
+7 -7
@@ -20,19 +20,19 @@ function component(a) {
20 function component(a) {
21 const $ = React.useMemoCache();
22 const c_0 = $[0] !== a;
23 - let t1;
23 + let t0;
24 if (c_0) {
25 - t1 = { a: a };
25 + t0 = { a: a };
26 $[0] = a;
27 - $[1] = t1;
27 + $[1] = t0;
28 } else {
29 - t1 = $[1];
29 + t0 = $[1];
30 }
31 - const c_2 = $[2] !== t1;
31 + const c_2 = $[2] !== t0;
32 let z;
33 if (c_2) {
34 - z = { a: t1 };
35 - $[2] = t1;
34 + z = { a: t0 };
35 + $[2] = t0;
36 $[3] = z;
37 } else {
38 z = $[3];
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md
+7 -7
@@ -18,19 +18,19 @@ function component(a) {
18 function component(a) {
19 const $ = React.useMemoCache();
20 const c_0 = $[0] !== a;
21 - let t1;
21 + let t0;
22 if (c_0) {
23 - t1 = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = t1;
25 + $[1] = t0;
26 } else {
27 - t1 = $[1];
27 + t0 = $[1];
28 }
29 - const c_2 = $[2] !== t1;
29 + const c_2 = $[2] !== t0;
30 let z;
31 if (c_2) {
32 - z = { a: t1 };
33 - $[2] = t1;
32 + z = { a: t0 };
33 + $[2] = t0;
34 $[3] = z;
35 } else {
36 z = $[3];
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+12 -12
@@ -74,31 +74,31 @@ function Component(props) {
74
75 const count = renderedItems.length;
76 const c_5 = $[5] !== count;
77 - let t6;
77 + let t0;
78 if (c_5) {
79 - t6 = <h1>{count} Items</h1>;
79 + t0 = <h1>{count} Items</h1>;
80 $[5] = count;
81 - $[6] = t6;
81 + $[6] = t0;
82 } else {
83 - t6 = $[6];
83 + t0 = $[6];
84 }
85 - const c_7 = $[7] !== t6;
85 + const c_7 = $[7] !== t0;
86 const c_8 = $[8] !== renderedItems;
87 - let t9;
87 + let t1;
88 if (c_7 || c_8) {
89 - t9 = (
89 + t1 = (
90 <div>
91 - {t6}
91 + {t0}
92 {renderedItems}
93 </div>
94 );
95 - $[7] = t6;
95 + $[7] = t0;
96 $[8] = renderedItems;
97 - $[9] = t9;
97 + $[9] = t1;
98 } else {
99 - t9 = $[9];
99 + t1 = $[9];
100 }
101 - return t9;
101 + return t1;
102 }
103
104 ```
compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md
+9 -13
@@ -24,25 +24,21 @@ function component() {
24 }
25 const x = t0[0];
26 const setX = t0[1];
27 - const c_1 = $[1] !== setX;
27 let handler;
29 - if (c_1) {
28 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29 handler = (v) => setX(v);
31 - $[1] = setX;
32 - $[2] = handler;
30 + $[1] = handler;
31 } else {
34 - handler = $[2];
32 + handler = $[1];
33 }
36 - const c_3 = $[3] !== handler;
37 - let t4;
38 - if (c_3) {
39 - t4 = <Foo handler={handler}></Foo>;
40 - $[3] = handler;
41 - $[4] = t4;
34 + let t1;
35 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
36 + t1 = <Foo handler={handler}></Foo>;
37 + $[2] = t1;
38 } else {
43 - t4 = $[4];
39 + t1 = $[2];
40 }
45 - return t4;
41 + return t1;
42 }
43
44 ```
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+10 -10
@@ -61,16 +61,16 @@ function ComponentA(props) {
61 }
62 const c_5 = $[5] !== a;
63 const c_6 = $[6] !== b;
64 - let t7;
64 + let t0;
65 if (c_5 || c_6) {
66 - t7 = <Foo a={a} b={b}></Foo>;
66 + t0 = <Foo a={a} b={b}></Foo>;
67 $[5] = a;
68 $[6] = b;
69 - $[7] = t7;
69 + $[7] = t0;
70 } else {
71 - t7 = $[7];
71 + t0 = $[7];
72 }
73 - return t7;
73 + return t0;
74 }
75
76 function ComponentB(props) {
@@ -100,16 +100,16 @@ function ComponentB(props) {
100 }
101 const c_5 = $[5] !== a;
102 const c_6 = $[6] !== b;
103 - let t7;
103 + let t0;
104 if (c_5 || c_6) {
105 - t7 = <Foo a={a} b={b}></Foo>;
105 + t0 = <Foo a={a} b={b}></Foo>;
106 $[5] = a;
107 $[6] = b;
108 - $[7] = t7;
108 + $[7] = t0;
109 } else {
110 - t7 = $[7];
110 + t0 = $[7];
111 }
112 - return t7;
112 + return t0;
113 }
114
115 function Foo() {}
compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md
+6 -10
@@ -37,18 +37,14 @@ function Component(props) {
37 a = $[0];
38 b = $[1];
39 }
40 - const c_2 = $[2] !== a;
41 - const c_3 = $[3] !== b;
42 - let t4;
43 - if (c_2 || c_3) {
44 - t4 = <div a={a} b={b}></div>;
45 - $[2] = a;
46 - $[3] = b;
47 - $[4] = t4;
40 + let t0;
41 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
42 + t0 = <div a={a} b={b}></div>;
43 + $[2] = t0;
44 } else {
49 - t4 = $[4];
45 + t0 = $[2];
46 }
51 - return t4;
47 + return t0;
48 }
49
50 ```
compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md
+9 -15
@@ -34,33 +34,27 @@ function Component(props) {
34 } else {
35 x = $[0];
36 }
37 - const c_1 = $[1] !== x;
37 let y;
39 - if (c_1) {
38 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
39 y = useFreeze(x);
41 - $[1] = x;
42 - $[2] = y;
40 + $[1] = y;
41 } else {
44 - y = $[2];
42 + y = $[1];
43 }
44 foo(y, x);
47 - const c_3 = $[3] !== x;
48 - const c_4 = $[4] !== y;
49 - let t5;
50 - if (c_3 || c_4) {
51 - t5 = (
45 + let t0;
46 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
47 + t0 = (
48 <Component>
49 {x}
50 {y}
51 </Component>
52 );
57 - $[3] = x;
58 - $[4] = y;
59 - $[5] = t5;
53 + $[2] = t0;
54 } else {
61 - t5 = $[5];
55 + t0 = $[2];
56 }
63 - return t5;
57 + return t0;
58 }
59
60 ```
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+5 -5
@@ -80,16 +80,16 @@ function Component(props) {
80 }
81 const c_5 = $[5] !== a;
82 const c_6 = $[6] !== b;
83 - let t7;
83 + let t0;
84 if (c_5 || c_6) {
85 - t7 = <Foo a={a} b={b}></Foo>;
85 + t0 = <Foo a={a} b={b}></Foo>;
86 $[5] = a;
87 $[6] = b;
88 - $[7] = t7;
88 + $[7] = t0;
89 } else {
90 - t7 = $[7];
90 + t0 = $[7];
91 }
92 - return t7;
92 + return t0;
93 }
94
95 ```
compiler/forget/src/__tests__/fixtures/hir/independent.expect.md
+5 -5
@@ -59,16 +59,16 @@ function Component(props) {
59 }
60 const c_4 = $[4] !== a;
61 const c_5 = $[5] !== b;
62 - let t6;
62 + let t0;
63 if (c_4 || c_5) {
64 - t6 = <Foo a={a} b={b}></Foo>;
64 + t0 = <Foo a={a} b={b}></Foo>;
65 $[4] = a;
66 $[5] = b;
67 - $[6] = t6;
67 + $[6] = t0;
68 } else {
69 - t6 = $[6];
69 + t0 = $[6];
70 }
71 - return t6;
71 + return t0;
72 }
73
74 function compute() {}
compiler/forget/src/__tests__/fixtures/hir/independently-memoize-object-property.expect.md
+5 -5
@@ -25,16 +25,16 @@ function foo(a, b, c) {
25 x = { a: a };
26 const c_4 = $[4] !== b;
27 const c_5 = $[5] !== c;
28 - let t6;
28 + let t0;
29 if (c_4 || c_5) {
30 - t6 = [b, c];
30 + t0 = [b, c];
31 $[4] = b;
32 $[5] = c;
33 - $[6] = t6;
33 + $[6] = t0;
34 } else {
35 - t6 = $[6];
35 + t0 = $[6];
36 }
37 - x.y = t6;
37 + x.y = t0;
38 $[0] = a;
39 $[1] = b;
40 $[2] = c;
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+5 -5
@@ -68,16 +68,16 @@ function Component(props) {
68 }
69 const c_5 = $[5] !== a;
70 const c_6 = $[6] !== b;
71 - let t7;
71 + let t0;
72 if (c_5 || c_6) {
73 - t7 = <Foo a={a} b={b}></Foo>;
73 + t0 = <Foo a={a} b={b}></Foo>;
74 $[5] = a;
75 $[6] = b;
76 - $[7] = t7;
76 + $[7] = t0;
77 } else {
78 - t7 = $[7];
78 + t0 = $[7];
79 }
80 - return t7;
80 + return t0;
81 }
82
83 ```
compiler/forget/src/__tests__/fixtures/hir/interdependent.expect.md
+5 -5
@@ -56,16 +56,16 @@ function Component(props) {
56 }
57 const c_4 = $[4] !== a;
58 const c_5 = $[5] !== b;
59 - let t6;
59 + let t0;
60 if (c_4 || c_5) {
61 - t6 = <Foo a={a} b={b}></Foo>;
61 + t0 = <Foo a={a} b={b}></Foo>;
62 $[4] = a;
63 $[5] = b;
64 - $[6] = t6;
64 + $[6] = t0;
65 } else {
66 - t6 = $[6];
66 + t0 = $[6];
67 }
68 - return t6;
68 + return t0;
69 }
70
71 function compute() {}
compiler/forget/src/__tests__/fixtures/hir/jsx-fragment.expect.md
+14 -18
@@ -27,32 +27,28 @@ function Foo(props) {
27 } else {
28 t0 = $[0];
29 }
30 - const c_1 = $[1] !== t0;
31 - let t2;
32 - if (c_1) {
33 - t2 = <div>{t0}</div>;
34 - $[1] = t0;
35 - $[2] = t2;
30 + let t1;
31 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
32 + t1 = <div>{t0}</div>;
33 + $[1] = t1;
34 } else {
37 - t2 = $[2];
35 + t1 = $[1];
36 }
39 - const c_3 = $[3] !== props.greeting;
40 - const c_4 = $[4] !== t2;
41 - let t5;
42 - if (c_3 || c_4) {
43 - t5 = (
37 + const c_2 = $[2] !== props.greeting;
38 + let t2;
39 + if (c_2) {
40 + t2 = (
41 <>
42 Hello {props.greeting}
46 - {t2}
43 + {t1}
44 </>
45 );
49 - $[3] = props.greeting;
50 - $[4] = t2;
51 - $[5] = t5;
46 + $[2] = props.greeting;
47 + $[3] = t2;
48 } else {
53 - t5 = $[5];
49 + t2 = $[3];
50 }
55 - return t5;
51 + return t2;
52 }
53
54 ```
compiler/forget/src/__tests__/fixtures/hir/jsx-spread.expect.md
+17 -17
@@ -16,35 +16,35 @@ function Component(props) {
16 function Component(props) {
17 const $ = React.useMemoCache();
18 const c_0 = $[0] !== props;
19 - let t1;
19 + let t0;
20 if (c_0) {
21 - t1 = props.cond ? props.foo : props.bar;
21 + t0 = props.cond ? props.foo : props.bar;
22 $[0] = props;
23 - $[1] = t1;
23 + $[1] = t0;
24 } else {
25 - t1 = $[1];
25 + t0 = $[1];
26 }
27 - const c_2 = $[2] !== t1;
28 - let t3;
27 + const c_2 = $[2] !== t0;
28 + let t1;
29 if (c_2) {
30 - t3 = { bar: t1 };
31 - $[2] = t1;
32 - $[3] = t3;
30 + t1 = { bar: t0 };
31 + $[2] = t0;
32 + $[3] = t1;
33 } else {
34 - t3 = $[3];
34 + t1 = $[3];
35 }
36 const c_4 = $[4] !== props;
37 - const c_5 = $[5] !== t3;
38 - let t6;
37 + const c_5 = $[5] !== t1;
38 + let t2;
39 if (c_4 || c_5) {
40 - t6 = <Component {...props} {...t3}></Component>;
40 + t2 = <Component {...props} {...t1}></Component>;
41 $[4] = props;
42 - $[5] = t3;
43 - $[6] = t6;
42 + $[5] = t1;
43 + $[6] = t2;
44 } else {
45 - t6 = $[6];
45 + t2 = $[6];
46 }
47 - return t6;
47 + return t2;
48 }
49
50 ```
compiler/forget/src/__tests__/fixtures/hir/logical-expression-object.expect.md
+15 -15
@@ -21,37 +21,37 @@ function component(props) {
21 function component(props) {
22 const $ = React.useMemoCache();
23 const c_0 = $[0] !== props;
24 - let t1;
24 + let t0;
25 if (c_0) {
26 - t1 = props.a || (props.b && props.c && props.d);
26 + t0 = props.a || (props.b && props.c && props.d);
27 $[0] = props;
28 - $[1] = t1;
28 + $[1] = t0;
29 } else {
30 - t1 = $[1];
30 + t0 = $[1];
31 }
32 - const a = t1;
32 + const a = t0;
33 const c_2 = $[2] !== props;
34 - let t3;
34 + let t1;
35 if (c_2) {
36 - t3 = (props.a && props.b && props.c) || props.d;
36 + t1 = (props.a && props.b && props.c) || props.d;
37 $[2] = props;
38 - $[3] = t3;
38 + $[3] = t1;
39 } else {
40 - t3 = $[3];
40 + t1 = $[3];
41 }
42 - const b = t3;
42 + const b = t1;
43 const c_4 = $[4] !== a;
44 const c_5 = $[5] !== b;
45 - let t6;
45 + let t2;
46 if (c_4 || c_5) {
47 - t6 = { a: a, b: b };
47 + t2 = { a: a, b: b };
48 $[4] = a;
49 $[5] = b;
50 - $[6] = t6;
50 + $[6] = t2;
51 } else {
52 - t6 = $[6];
52 + t2 = $[6];
53 }
54 - return t6;
54 + return t2;
55 }
56
57 ```
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+15 -15
@@ -16,39 +16,39 @@ function component(props) {
16 function component(props) {
17 const $ = React.useMemoCache();
18 const c_0 = $[0] !== props;
19 - let t1;
19 + let t0;
20 if (c_0) {
21 - t1 = props.a || (props.b && props.c && props.d);
21 + t0 = props.a || (props.b && props.c && props.d);
22 $[0] = props;
23 - $[1] = t1;
23 + $[1] = t0;
24 } else {
25 - t1 = $[1];
25 + t0 = $[1];
26 }
27 - const a = t1;
27 + const a = t0;
28 const c_2 = $[2] !== props;
29 - let t3;
29 + let t1;
30 if (c_2) {
31 - t3 = (props.a && props.b && props.c) || props.d;
31 + t1 = (props.a && props.b && props.c) || props.d;
32 $[2] = props;
33 - $[3] = t3;
33 + $[3] = t1;
34 } else {
35 - t3 = $[3];
35 + t1 = $[3];
36 }
37 - const b = t3;
37 + const b = t1;
38 const c_4 = $[4] !== a;
39 const c_5 = $[5] !== b;
40 const c_6 = $[6] !== props;
41 - let t7;
41 + let t2;
42 if (c_4 || c_5 || c_6) {
43 - t7 = a ? b : props.c;
43 + t2 = a ? b : props.c;
44 $[4] = a;
45 $[5] = b;
46 $[6] = props;
47 - $[7] = t7;
47 + $[7] = t2;
48 } else {
49 - t7 = $[7];
49 + t2 = $[7];
50 }
51 - return t7;
51 + return t2;
52 }
53
54 ```
compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md
+5 -5
@@ -37,16 +37,16 @@ function component(t8) {
37 }
38 const c_4 = $[4] !== y;
39 const c_5 = $[5] !== z;
40 - let t6;
40 + let t0;
41 if (c_4 || c_5) {
42 - t6 = { y: y, z: z };
42 + t0 = { y: y, z: z };
43 $[4] = y;
44 $[5] = z;
45 - $[6] = t6;
45 + $[6] = t0;
46 } else {
47 - t6 = $[6];
47 + t0 = $[6];
48 }
49 - return t6;
49 + return t0;
50 }
51
52 ```
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-shadowing-within-block.expect.md
+5 -5
@@ -44,15 +44,15 @@ function foo(a, b, c) {
44 y = $[6];
45 }
46 const c_7 = $[7] !== y;
47 - let t8;
47 + let t0;
48 if (c_7) {
49 - t8 = <div>{y}</div>;
49 + t0 = <div>{y}</div>;
50 $[7] = y;
51 - $[8] = t8;
51 + $[8] = t0;
52 } else {
53 - t8 = $[8];
53 + t0 = $[8];
54 }
55 - x.push(t8);
55 + x.push(t0);
56 }
57 $[0] = a;
58 $[1] = b;
compiler/forget/src/__tests__/fixtures/hir/property-assignment.expect.md
+5 -5
@@ -37,16 +37,16 @@ function Component(props) {
37 }
38 const c_3 = $[3] !== x;
39 const c_4 = $[4] !== child;
40 - let t5;
40 + let t0;
41 if (c_3 || c_4) {
42 - t5 = <Component data={x}>{child}</Component>;
42 + t0 = <Component data={x}>{child}</Component>;
43 $[3] = x;
44 $[4] = child;
45 - $[5] = t5;
45 + $[5] = t0;
46 } else {
47 - t5 = $[5];
47 + t0 = $[5];
48 }
49 - return t5;
49 + return t0;
50 }
51
52 ```
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes-if.expect.md
+5 -5
@@ -39,15 +39,15 @@ function foo(a, b, c) {
39 y = $[5];
40 }
41 const c_6 = $[6] !== y;
42 - let t7;
42 + let t0;
43 if (c_6) {
44 - t7 = <div>{y}</div>;
44 + t0 = <div>{y}</div>;
45 $[6] = y;
46 - $[7] = t7;
46 + $[7] = t0;
47 } else {
48 - t7 = $[7];
48 + t0 = $[7];
49 }
50 - x.push(t7);
50 + x.push(t0);
51 } else {
52 x.push(c);
53 }
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes.expect.md
+5 -5
@@ -37,15 +37,15 @@ function f(a, b) {
37 x = $[2];
38 }
39 const c_3 = $[3] !== x;
40 - let t4;
40 + let t0;
41 if (c_3) {
42 - t4 = <div>{x}</div>;
42 + t0 = <div>{x}</div>;
43 $[3] = x;
44 - $[4] = t4;
44 + $[4] = t0;
45 } else {
46 - t4 = $[4];
46 + t0 = $[4];
47 }
48 - return t4;
48 + return t0;
49 }
50
51 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+5 -5
@@ -59,16 +59,16 @@ function Component(props) {
59 y.push(props.p2);
60 const c_5 = $[5] !== x$0;
61 const c_6 = $[6] !== y;
62 - let t7;
62 + let t0;
63 if (c_5 || c_6) {
64 - t7 = <Component x={x$0} y={y}></Component>;
64 + t0 = <Component x={x$0} y={y}></Component>;
65 $[5] = x$0;
66 $[6] = y;
67 - $[7] = t7;
67 + $[7] = t0;
68 } else {
69 - t7 = $[7];
69 + t0 = $[7];
70 }
71 - return t7;
71 + return t0;
72 }
73
74 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+5 -5
@@ -98,9 +98,9 @@ function foo(a, b, c) {
98 }
99 const c_11 = $[11] !== y;
100 const c_12 = $[12] !== x$0;
101 - let t13;
101 + let t0;
102 if (c_11 || c_12) {
103 - t13 = (
103 + t0 = (
104 <div>
105 {y}
106 {x$0}
@@ -108,11 +108,11 @@ function foo(a, b, c) {
108 );
109 $[11] = y;
110 $[12] = x$0;
111 - $[13] = t13;
111 + $[13] = t0;
112 } else {
113 - t13 = $[13];
113 + t0 = $[13];
114 }
115 - return t13;
115 + return t0;
116 }
117
118 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md
+8 -10
@@ -45,18 +45,16 @@ function Component(props) {
45 } else {
46 y = $[2];
47 }
48 - const c_4 = $[4] !== x$0;
49 - const c_5 = $[5] !== y;
50 - let t6;
51 - if (c_4 || c_5) {
52 - t6 = <Component x={x$0} y={y}></Component>;
53 - $[4] = x$0;
54 - $[5] = y;
55 - $[6] = t6;
48 + const c_4 = $[4] !== y;
49 + let t0;
50 + if (c_4) {
51 + t0 = <Component x={x$0} y={y}></Component>;
52 + $[4] = y;
53 + $[5] = t0;
54 } else {
57 - t6 = $[6];
55 + t0 = $[5];
56 }
59 - return t6;
57 + return t0;
58 }
59
60 ```
compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md
+3 -5
@@ -28,19 +28,17 @@ function sequence(props) {
28 } else {
29 t0 = $[0];
30 }
31 - const c_1 = $[1] !== t0;
31 let x;
33 - if (c_1) {
32 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
33 x = t0;
34 while ((foo(), true)) {
35 foo();
36 2;
37 x = 2;
38 }
40 - $[1] = t0;
41 - $[2] = x;
39 + $[1] = x;
40 } else {
43 - x = $[2];
41 + x = $[1];
42 }
43 return x;
44 }
compiler/forget/src/__tests__/fixtures/hir/simple.expect.md
+13 -9
@@ -18,22 +18,26 @@ export default function foo(x, y) {
18 const $ = React.useMemoCache();
19 if (x) {
20 const c_0 = $[0] !== y;
21 - let t1;
21 + let t0;
22 if (c_0) {
23 - t1 = foo(false, y);
23 + t0 = foo(false, y);
24 $[0] = y;
25 - $[1] = t1;
25 + $[1] = t0;
26 } else {
27 - t1 = $[1];
27 + t0 = $[1];
28 }
29 - return t1;
29 + return t0;
30 }
31 +
32 + const t1 = y * 10;
33 + const c_2 = $[2] !== t1;
34 let t2;
32 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
33 - t2 = [y * 10];
34 - $[2] = t2;
35 + if (c_2) {
36 + t2 = [t1];
37 + $[2] = t1;
38 + $[3] = t2;
39 } else {
36 - t2 = $[2];
40 + t2 = $[3];
41 }
42 return t2;
43 }
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx-2.expect.md
+11 -15
@@ -32,14 +32,14 @@ function Component(props) {
32 a = [];
33 b = {};
34 foo(a, b);
35 - let t2;
35 + let t0;
36 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
37 - t2 = foo();
38 - $[2] = t2;
37 + t0 = foo();
38 + $[2] = t0;
39 } else {
40 - t2 = $[2];
40 + t0 = $[2];
41 }
42 - if (t2) {
42 + if (t0) {
43 const _ = <div a={a}></div>;
44 }
45
@@ -50,18 +50,14 @@ function Component(props) {
50 a = $[0];
51 b = $[1];
52 }
53 - const c_3 = $[3] !== a;
54 - const c_4 = $[4] !== b;
55 - let t5;
56 - if (c_3 || c_4) {
57 - t5 = <div a={a} b={b}></div>;
58 - $[3] = a;
59 - $[4] = b;
60 - $[5] = t5;
53 + let t1;
54 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
55 + t1 = <div a={a} b={b}></div>;
56 + $[3] = t1;
57 } else {
62 - t5 = $[5];
58 + t1 = $[3];
59 }
64 - return t5;
60 + return t1;
61 }
62
63 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md
+6 -10
@@ -36,18 +36,14 @@ function Component(props) {
36 a = $[0];
37 b = $[1];
38 }
39 - const c_2 = $[2] !== a;
40 - const c_3 = $[3] !== b;
41 - let t4;
42 - if (c_2 || c_3) {
43 - t4 = <div a={a} b={b}></div>;
44 - $[2] = a;
45 - $[3] = b;
46 - $[4] = t4;
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 {
48 - t4 = $[4];
44 + t0 = $[2];
45 }
50 - return t4;
46 + return t0;
47 }
48
49 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md
+3 -5
@@ -23,15 +23,13 @@ function foo() {
23 } else {
24 x = $[0];
25 }
26 - const c_1 = $[1] !== x;
26 let y;
28 - if (c_1) {
27 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
28 y = {};
29 y.x = x;
31 - $[1] = x;
32 - $[2] = y;
30 + $[1] = y;
31 } else {
34 - y = $[2];
32 + y = $[1];
33 }
34 return y;
35 }
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+5 -5
@@ -85,16 +85,16 @@ function Component(props) {
85 y$0.push(props.p4);
86 const c_7 = $[7] !== y$0;
87 const c_8 = $[8] !== child;
88 - let t9;
88 + let t0;
89 if (c_7 || c_8) {
90 - t9 = <Component data={y$0}>{child}</Component>;
90 + t0 = <Component data={y$0}>{child}</Component>;
91 $[7] = y$0;
92 $[8] = child;
93 - $[9] = t9;
93 + $[9] = t0;
94 } else {
95 - t9 = $[9];
95 + t0 = $[9];
96 }
97 - return t9;
97 + return t0;
98 }
99
100 ```
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+5 -5
@@ -69,16 +69,16 @@ function Component(props) {
69 y$0.push(props.p4);
70 const c_7 = $[7] !== y$0;
71 const c_8 = $[8] !== child;
72 - let t9;
72 + let t0;
73 if (c_7 || c_8) {
74 - t9 = <Component data={y$0}>{child}</Component>;
74 + t0 = <Component data={y$0}>{child}</Component>;
75 $[7] = y$0;
76 $[8] = child;
77 - $[9] = t9;
77 + $[9] = t0;
78 } else {
79 - t9 = $[9];
79 + t0 = $[9];
80 }
81 - return t9;
81 + return t0;
82 }
83
84 ```
compiler/forget/src/__tests__/fixtures/hir/ternary-expression.expect.md
+15 -15
@@ -16,37 +16,37 @@ function ternary(props) {
16 function ternary(props) {
17 const $ = React.useMemoCache();
18 const c_0 = $[0] !== props;
19 - let t1;
19 + let t0;
20 if (c_0) {
21 - t1 = props.a && props.b ? props.c || props.d : props.e ?? props.f;
21 + t0 = props.a && props.b ? props.c || props.d : props.e ?? props.f;
22 $[0] = props;
23 - $[1] = t1;
23 + $[1] = t0;
24 } else {
25 - t1 = $[1];
25 + t0 = $[1];
26 }
27 - const a = t1;
27 + const a = t0;
28 const c_2 = $[2] !== props;
29 - let t3;
29 + let t1;
30 if (c_2) {
31 - t3 = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
31 + t1 = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
32 $[2] = props;
33 - $[3] = t3;
33 + $[3] = t1;
34 } else {
35 - t3 = $[3];
35 + t1 = $[3];
36 }
37 - const b = t3;
37 + const b = t1;
38 const c_4 = $[4] !== a;
39 const c_5 = $[5] !== b;
40 - let t6;
40 + let t2;
41 if (c_4 || c_5) {
42 - t6 = a ? b : (null, null);
42 + t2 = a ? b : (null, null);
43 $[4] = a;
44 $[5] = b;
45 - $[6] = t6;
45 + $[6] = t2;
46 } else {
47 - t6 = $[6];
47 + t2 = $[6];
48 }
49 - return t6;
49 + return t2;
50 }
51
52 ```
compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md
+3 -7
@@ -34,16 +34,12 @@ function component() {
34 } else {
35 t1 = $[1];
36 }
37 - const c_2 = $[2] !== t0;
38 - const c_3 = $[3] !== t1;
37 let x;
40 - if (c_2 || c_3) {
38 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
39 x = { u: t0, v: t1 };
42 - $[2] = t0;
43 - $[3] = t1;
44 - $[4] = x;
40 + $[2] = x;
41 } else {
46 - x = $[4];
42 + x = $[2];
43 }
44 const u = x.u;
45 const v = x.v;
compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md
+3 -5
@@ -38,18 +38,16 @@ function component() {
38 } else {
39 o = $[1];
40 }
41 - const c_2 = $[2] !== o;
41 let x;
43 - if (c_2) {
42 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
43 x = {};
44 x.t = p;
45
46 const z = x.t;
47 x.t = o;
49 - $[2] = o;
50 - $[3] = x;
48 + $[2] = x;
49 } else {
52 - x = $[3];
50 + x = $[2];
51 }
52
53 const y = x.t;
compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md
+20 -6
@@ -37,14 +37,28 @@ function component(a) {
37 const m = !t.t;
38 const e = ~t.t;
39 const f = typeof t.t;
40 - let t2;
41 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
42 - t2 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f };
43 - $[2] = t2;
40 + const c_2 = $[2] !== z;
41 + const c_3 = $[3] !== p;
42 + const c_4 = $[4] !== q;
43 + const c_5 = $[5] !== n;
44 + const c_6 = $[6] !== m;
45 + const c_7 = $[7] !== e;
46 + const c_8 = $[8] !== f;
47 + let t0;
48 + if (c_2 || c_3 || c_4 || c_5 || c_6 || c_7 || c_8) {
49 + t0 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f };
50 + $[2] = z;
51 + $[3] = p;
52 + $[4] = q;
53 + $[5] = n;
54 + $[6] = m;
55 + $[7] = e;
56 + $[8] = f;
57 + $[9] = t0;
58 } else {
45 - t2 = $[2];
59 + t0 = $[9];
60 }
47 - return t2;
61 + return t0;
62 }
63
64 ```
compiler/forget/src/__tests__/fixtures/hir/update-expression.expect.md
+9 -3
@@ -21,12 +21,18 @@ function foo(props) {
21 const y = x$0;
22 const x$1 = x$0 - 1;
23 const z = x$1;
24 + const c_0 = $[0] !== x$1;
25 + const c_1 = $[1] !== y;
26 + const c_2 = $[2] !== z;
27 let t0;
25 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28 + if (c_0 || c_1 || c_2) {
29 t0 = { x: x$1, y: y, z: z };
27 - $[0] = t0;
30 + $[0] = x$1;
31 + $[1] = y;
32 + $[2] = z;
33 + $[3] = t0;
34 } else {
29 - t0 = $[0];
35 + t0 = $[3];
36 }
37 return t0;
38 }