@samitouri / QOS-React / commits / 487786f7d4

StoreLocal instruction

Adds a new `StoreLocal <kind> <place> = <value>` instruction which stores <value> into <place>. With this change, Instruction.lvalue is _always_ a `const` temporary, and never a named identifier (there's a new validation pass to assert this). StoreLocal is the only way to declare or update a named identifier: the instructionKind property says whether it's a const/let declaration or a reassignment. Naturally a _lot_ of passes had to be updated to make this work, but the existing Effect.Store variant that @gsathya added made this overall straightforward. Note that as of this PR several passes still have code to handle the possibility of an instruction lvalue being something other than a temporary. When we clean that up in a follow-up, there will be a lot less of the duplication that appears here. For example, CodegenReactiveFunction has two places to handle variable declarations in this PR. However, one of them is to handle lvalues, which should now _always_ be temporaries and never emit a regular variable declaration. Similarly, several passes have to build up a table of identifier -> identifier (because of LoadLocal). Longer-term, we should update the Place abstraction so that it directly specifies the instruction which created that temporary, so we can look it up on demand instead of needing an extra mapping.

Joe Savona committed Mar 2, 2023 at 14:19 UTC 487786f7d4a858cc0dda55e38d10436fad412bc5
90 files changed +1239 -752
compiler/forget/src/CompilerPipeline.ts
+3
@@ -13,6 +13,7 @@ import {
13 ReactiveFunction,
14 } from "./HIR";
15 import { EnvironmentOptions, mergeOptions } from "./HIR/Environment";
16 +import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers";
17 import {
18 analyseFunctions,
19 dropMemoCalls,
@@ -60,6 +61,8 @@ export function* run(
61 enterSSA(hir);
62 yield log({ kind: "hir", name: "SSA", value: hir });
63
64 + validateConsistentIdentifiers(hir);
65 +
66 eliminateRedundantPhi(hir);
67 yield log({ kind: "hir", name: "EliminateRedundantPhi", value: hir });
68
compiler/forget/src/HIR/BuildHIR.ts
+119 -65
@@ -110,7 +110,7 @@ export function lower(
110 param.node.loc ?? GeneratedSource,
111 InstructionKind.Let,
112 param,
113 - { kind: "LoadLocal", place, loc: place.loc }
113 + place
114 );
115 } else {
116 builder.errors.push({
@@ -590,7 +590,7 @@ function lowerStatement(
590 }
591 case "VariableDeclaration": {
592 const stmt = stmtPath as NodePath<t.VariableDeclaration>;
593 - const nodeKind: string = stmt.node.kind;
593 + const nodeKind: t.VariableDeclaration["kind"] = stmt.node.kind;
594 if (nodeKind === "var") {
595 builder.errors.push({
596 reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`,
@@ -604,15 +604,24 @@ function lowerStatement(
604 for (const declaration of stmt.get("declarations")) {
605 const id = declaration.get("id");
606 const init = declaration.get("init");
607 - let value: InstructionValue;
607 + let value: Place;
608 if (init.node != null) {
609 - value = lowerExpression(builder, init as NodePath<t.Expression>);
609 + value = lowerExpressionToTemporary(
610 + builder,
611 + init as NodePath<t.Expression>
612 + );
613 } else {
611 - value = {
612 - kind: "Primitive",
613 - value: undefined,
614 - loc: id.node.loc ?? GeneratedSource,
615 - };
614 + value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource);
615 + builder.push({
616 + id: makeInstructionId(0),
617 + lvalue: { place: { ...value }, kind: InstructionKind.Const },
618 + value: {
619 + kind: "Primitive",
620 + value: undefined,
621 + loc: id.node.loc ?? GeneratedSource,
622 + },
623 + loc: value.loc,
624 + });
625 }
626 lowerAssignment(
627 builder,
@@ -1177,7 +1186,7 @@ function lowerExpression(
1186 left.node.loc ?? GeneratedSource,
1187 InstructionKind.Reassign,
1188 left,
1180 - lowerExpression(builder, expr.get("right"))
1189 + lowerExpressionToTemporary(builder, expr.get("right"))
1190 );
1191 }
1192
@@ -1209,21 +1218,41 @@ function lowerExpression(
1218 switch (leftNode.type) {
1219 case "Identifier": {
1220 const leftExpr = left as NodePath<t.Identifier>;
1212 - const place = lowerIdentifier(builder, leftExpr);
1221 + const identifier = lowerIdentifier(builder, leftExpr);
1222 + const leftPlace = lowerExpressionToTemporary(builder, leftExpr);
1223 const right = lowerExpressionToTemporary(builder, expr.get("right"));
1224 + const binaryPlace = buildTemporaryPlace(builder, exprLoc);
1225 builder.push({
1226 id: makeInstructionId(0),
1216 - lvalue: { place: { ...place }, kind: InstructionKind.Reassign },
1227 + lvalue: {
1228 + place: { ...binaryPlace },
1229 + kind: InstructionKind.Const,
1230 + },
1231 value: {
1232 kind: "BinaryExpression",
1233 operator: binaryOperator,
1220 - left: { ...place },
1234 + left: leftPlace,
1235 right,
1236 loc: exprLoc,
1237 },
1238 loc: exprLoc,
1239 });
1226 - return { kind: "LoadLocal", place, loc: exprLoc };
1240 + const result = buildTemporaryPlace(builder, exprLoc);
1241 + builder.push({
1242 + id: makeInstructionId(0),
1243 + lvalue: { place: { ...result }, kind: InstructionKind.Const },
1244 + value: {
1245 + kind: "StoreLocal",
1246 + lvalue: {
1247 + place: { ...identifier },
1248 + kind: InstructionKind.Reassign,
1249 + },
1250 + value: { ...binaryPlace },
1251 + loc: exprLoc,
1252 + },
1253 + loc: exprLoc,
1254 + });
1255 + return { kind: "LoadLocal", place: identifier, loc: exprLoc };
1256 }
1257 case "MemberExpression": {
1258 // a.b.c += <right>
@@ -1546,13 +1575,13 @@ function lowerExpression(
1575 });
1576 return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
1577 }
1549 - const temp = buildTemporaryPlace(
1578 + const primitiveTemp = buildTemporaryPlace(
1579 builder,
1580 expr.node.loc ?? GeneratedSource
1581 );
1582 builder.push({
1583 id: makeInstructionId(0),
1555 - lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1584 + lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const },
1585 value: {
1586 kind: "Primitive",
1587 value: 1,
@@ -1560,18 +1589,39 @@ function lowerExpression(
1589 },
1590 loc: expr.node.loc ?? GeneratedSource,
1591 });
1592 + const temp = buildTemporaryPlace(
1593 + builder,
1594 + expr.node.loc ?? GeneratedSource
1595 + );
1596 const identifier = lowerIdentifier(
1597 builder,
1598 argument as NodePath<t.Identifier>
1599 );
1600 builder.push({
1601 id: makeInstructionId(0),
1569 - lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign },
1602 + lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1603 value: {
1604 kind: "BinaryExpression",
1605 operator: expr.node.operator === "++" ? "+" : "-",
1606 left: { ...identifier },
1574 - right: { ...temp },
1607 + right: { ...primitiveTemp },
1608 + loc: exprLoc,
1609 + },
1610 + loc: exprLoc,
1611 + });
1612 + builder.push({
1613 + id: makeInstructionId(0),
1614 + lvalue: {
1615 + place: buildTemporaryPlace(builder, exprLoc),
1616 + kind: InstructionKind.Const,
1617 + },
1618 + value: {
1619 + kind: "StoreLocal",
1620 + lvalue: {
1621 + place: { ...identifier },
1622 + kind: InstructionKind.Reassign,
1623 + },
1624 + value: { ...temp },
1625 loc: exprLoc,
1626 },
1627 loc: exprLoc,
@@ -1883,7 +1933,7 @@ function lowerAssignment(
1933 loc: SourceLocation,
1934 kind: InstructionKind,
1935 lvaluePath: NodePath<t.LVal>,
1886 - value: InstructionValue
1936 + value: Place
1937 ): InstructionValue {
1938 const lvalueNode = lvaluePath.node;
1939 switch (lvalueNode.type) {
@@ -1913,6 +1963,7 @@ function lowerAssignment(
1963 };
1964 }
1965
1966 + const temporary = buildTemporaryPlace(builder, loc);
1967 const place: Place = {
1968 kind: "Identifier",
1969 identifier: identifier,
@@ -1921,28 +1972,24 @@ function lowerAssignment(
1972 };
1973 builder.push({
1974 id: makeInstructionId(0),
1924 - lvalue: { place: { ...place }, kind },
1925 - value,
1975 + lvalue: { place: { ...temporary }, kind },
1976 + value: {
1977 + kind: "StoreLocal",
1978 + lvalue: {
1979 + place: { ...place },
1980 + kind,
1981 + },
1982 + value,
1983 + loc,
1984 + },
1985 loc,
1986 });
1928 - return { kind: "LoadLocal", place, loc: place.loc };
1987 + return { kind: "LoadLocal", place, loc: temporary.loc };
1988 }
1989 case "MemberExpression": {
1990 const lvalue = lvaluePath as NodePath<t.MemberExpression>;
1991 const property = lvalue.get("property");
1992 const object = lowerExpressionToTemporary(builder, lvalue.get("object"));
1934 - let valuePlace: Place;
1935 - if (value.kind === "LoadLocal") {
1936 - valuePlace = value.place;
1937 - } else {
1938 - valuePlace = buildTemporaryPlace(builder, loc);
1939 - builder.push({
1940 - id: makeInstructionId(0),
1941 - lvalue: { place: { ...valuePlace }, kind: InstructionKind.Const },
1942 - value,
1943 - loc,
1944 - });
1945 - }
1993 if (!lvalue.node.computed) {
1994 if (!property.isIdentifier()) {
1995 builder.errors.push({
@@ -1956,7 +2003,7 @@ function lowerAssignment(
2003 kind: "PropertyStore",
2004 object,
2005 property: property.node.name,
1959 - value: valuePlace,
2006 + value,
2007 loc,
2008 };
2009 } else {
@@ -1974,20 +2021,13 @@ function lowerAssignment(
2021 kind: "ComputedStore",
2022 object,
2023 property: propertyPlace,
1977 - value: valuePlace,
2024 + value,
2025 loc,
2026 };
2027 }
2028 }
2029 case "ArrayPattern": {
2030 const lvalue = lvaluePath as NodePath<t.ArrayPattern>;
1984 - const arrayPlace = buildTemporaryPlace(builder, loc);
1985 - builder.push({
1986 - id: makeInstructionId(0),
1987 - lvalue: { place: { ...arrayPlace }, kind: InstructionKind.Const },
1988 - value,
1989 - loc,
1990 - });
2031 const elements = lvalue.get("elements");
2032 let hasError = false;
2033 for (let i = 0; i < elements.length; i++) {
@@ -2018,27 +2058,32 @@ function lowerAssignment(
2058 },
2059 loc: element.node.loc ?? GeneratedSource,
2060 });
2021 - const value: InstructionValue = {
2022 - kind: "ComputedLoad",
2061 + const propertyPlace = buildTemporaryPlace(builder, property.loc);
2062 + builder.push({
2063 + id: makeInstructionId(0),
2064 + lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2065 + value: {
2066 + kind: "ComputedLoad",
2067 + loc,
2068 + object: { ...value },
2069 + property,
2070 + },
2071 loc,
2024 - object: { ...arrayPlace },
2025 - property,
2026 - };
2027 - lowerAssignment(builder, loc, kind, element as NodePath<t.LVal>, value);
2072 + });
2073 + lowerAssignment(
2074 + builder,
2075 + loc,
2076 + kind,
2077 + element as NodePath<t.LVal>,
2078 + propertyPlace
2079 + );
2080 }
2081 return hasError
2082 ? { kind: "UnsupportedNode", node: lvalueNode, loc }
2031 - : { kind: "LoadLocal", place: arrayPlace, loc: arrayPlace.loc };
2083 + : { kind: "LoadLocal", place: value, loc: value.loc };
2084 }
2085 case "ObjectPattern": {
2086 const lvalue = lvaluePath as NodePath<t.ObjectPattern>;
2035 - const objectPlace = buildTemporaryPlace(builder, loc);
2036 - builder.push({
2037 - id: makeInstructionId(0),
2038 - lvalue: { place: { ...objectPlace }, kind },
2039 - value,
2040 - loc,
2041 - });
2087 const properties = lvalue.get("properties");
2088 let hasError = false;
2089 for (let i = 0; i < properties.length; i++) {
@@ -2072,18 +2117,27 @@ function lowerAssignment(
2117 hasError = true;
2118 continue;
2119 }
2075 - const value: InstructionValue = {
2076 - kind: "PropertyLoad",
2120 + const propertyPlace = buildTemporaryPlace(
2121 + builder,
2122 + property.node.loc ?? GeneratedSource
2123 + );
2124 + builder.push({
2125 + id: makeInstructionId(0),
2126 + lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2127 + value: {
2128 + kind: "PropertyLoad",
2129 + loc,
2130 + object: { ...value },
2131 + property: key.node.name,
2132 + optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional.
2133 + },
2134 loc,
2078 - object: { ...objectPlace },
2079 - property: key.node.name,
2080 - optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional.
2081 - };
2082 - lowerAssignment(builder, loc, kind, element, value);
2135 + });
2136 + lowerAssignment(builder, loc, kind, element, propertyPlace);
2137 }
2138 return hasError
2139 ? { kind: "UnsupportedNode", node: lvalueNode, loc }
2086 - : { kind: "LoadLocal", place: objectPlace, loc: objectPlace.loc };
2140 + : { kind: "LoadLocal", place: value, loc: value.loc };
2141 }
2142 default: {
2143 builder.errors.push({
compiler/forget/src/HIR/HIR.ts
+6
@@ -418,6 +418,12 @@ export type InstructionValue =
418 place: Place;
419 loc: SourceLocation;
420 }
421 + | {
422 + kind: "StoreLocal";
423 + lvalue: LValue;
424 + value: Place;
425 + loc: SourceLocation;
426 + }
427 | {
428 kind: "Primitive";
429 value: number | boolean | string | null | undefined;
compiler/forget/src/HIR/PrintHIR.ts
+20
@@ -315,6 +315,12 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
315 value = `LoadLocal ${printPlace(instrValue.place)}`;
316 break;
317 }
318 + case "StoreLocal": {
319 + value = `StoreLocal ${instrValue.lvalue.kind} ${printPlace(
320 + instrValue.lvalue.place
321 + )} = ${printPlace(instrValue.value)}`;
322 + break;
323 + }
324 case "PropertyLoad": {
325 value = `PropertyLoad ${printPlace(instrValue.object)}.${
326 instrValue.property
@@ -412,6 +418,20 @@ function isMutable(range: MutableRange): boolean {
418 }
419
420 function printMutableRange(identifier: Identifier): string {
421 + invariant(
422 + (identifier.mutableRange.start === 0 &&
423 + identifier.mutableRange.end === 0) ||
424 + identifier.mutableRange.end > identifier.mutableRange.start,
425 + "Identifier mutableRange was invalid: [%s:%s]",
426 + identifier.mutableRange.start,
427 + identifier.mutableRange.end
428 + );
429 + if (identifier.scope !== null) {
430 + invariant(
431 + identifier.scope.range.end > identifier.scope.range.start,
432 + "Identifier scope mutableRange was invalid"
433 + );
434 + }
435 const range =
436 identifier.scope !== null
437 ? identifier.scope.range
compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts new
+69
@@ -0,0 +1,69 @@
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 { CompilerError } from "../CompilerError";
9 +import {
10 + GeneratedSource,
11 + HIRFunction,
12 + Identifier,
13 + IdentifierId,
14 + SourceLocation,
15 +} from "./HIR";
16 +import { eachInstructionValueOperand, eachTerminalOperand } from "./visitors";
17 +
18 +/**
19 + * Validation pass to check that there is a 1:1 mapping between Identifier objects and IdentifierIds,
20 + * ie there can only be one Identifier instance per IdentifierId.
21 + */
22 +export function validateConsistentIdentifiers(fn: HIRFunction): void {
23 + const identifiers: Identifiers = new Map();
24 + for (const [, block] of fn.body.blocks) {
25 + for (const phi of block.phis) {
26 + validate(identifiers, phi.id);
27 + for (const [, operand] of phi.operands) {
28 + validate(identifiers, operand);
29 + }
30 + }
31 + for (const instr of block.instructions) {
32 + if (instr.lvalue.place.identifier.name !== null) {
33 + CompilerError.invariant(
34 + `Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`,
35 + instr.lvalue.place.loc
36 + );
37 + }
38 + validate(
39 + identifiers,
40 + instr.lvalue.place.identifier,
41 + instr.lvalue.place.loc
42 + );
43 + for (const operand of eachInstructionValueOperand(instr.value)) {
44 + validate(identifiers, operand.identifier, operand.loc);
45 + }
46 + }
47 + for (const operand of eachTerminalOperand(block.terminal)) {
48 + validate(identifiers, operand.identifier, operand.loc);
49 + }
50 + }
51 +}
52 +
53 +type Identifiers = Map<IdentifierId, Identifier>;
54 +
55 +function validate(
56 + identifiers: Identifiers,
57 + identifier: Identifier,
58 + loc: SourceLocation | null = null
59 +): void {
60 + const previous = identifiers.get(identifier.id);
61 + if (previous === undefined) {
62 + identifiers.set(identifier.id, identifier);
63 + } else if (identifier !== previous) {
64 + CompilerError.invariant(
65 + `Duplicate identifier for id ${identifier.id}`,
66 + loc ?? GeneratedSource
67 + );
68 + }
69 +}
compiler/forget/src/HIR/visitors.ts
+10
@@ -52,6 +52,11 @@ export function* eachInstructionValueOperand(
52 yield instrValue.place;
53 break;
54 }
55 + case "StoreLocal": {
56 + yield instrValue.lvalue.place;
57 + yield instrValue.value;
58 + break;
59 + }
60 case "PropertyLoad": {
61 yield instrValue.object;
62 break;
@@ -181,6 +186,11 @@ export function mapInstructionOperands(
186 instrValue.place = fn(instrValue.place);
187 break;
188 }
189 + case "StoreLocal": {
190 + instrValue.lvalue.place = fn(instrValue.lvalue.place);
191 + instrValue.value = fn(instrValue.value);
192 + break;
193 + }
194 case "NewExpression":
195 case "CallExpression": {
196 instrValue.callee = fn(instrValue.callee);
compiler/forget/src/Inference/InferAlias.ts
+10 -14
@@ -3,33 +3,24 @@ import {
3 Identifier,
4 Instruction,
5 isPrimitiveType,
6 - LValue,
6 Place,
7 } from "../HIR/HIR";
8 import DisjointSet from "../Utils/DisjointSet";
9
10 export type AliasSet = Set<Identifier>;
11
13 -class AliasAnalyser {
14 - aliases = new DisjointSet<Identifier>();
15 -
16 - alias(lvalue: LValue, alias: Place) {
17 - this.aliases.union([lvalue.place.identifier, alias.identifier]);
18 - }
19 -}
20 -
12 export function inferAliases(func: HIRFunction): DisjointSet<Identifier> {
22 - const analyser = new AliasAnalyser();
13 + const aliases = new DisjointSet<Identifier>();
14 for (const [_, block] of func.body.blocks) {
15 for (const instr of block.instructions) {
25 - inferInstr(instr, analyser);
16 + inferInstr(instr, aliases);
17 }
18 }
19
29 - return analyser.aliases;
20 + return aliases;
21 }
22
32 -function inferInstr(instr: Instruction, state: AliasAnalyser) {
23 +function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
24 const { lvalue, value: instrValue } = instr;
25 let alias: Place | null = null;
26 switch (instrValue.kind) {
@@ -40,6 +31,11 @@ function inferInstr(instr: Instruction, state: AliasAnalyser) {
31 alias = instrValue.place;
32 break;
33 }
34 + case "StoreLocal": {
35 + // aliases.union([instrValue.place.identifier, instrValue.value.identifier]);
36 + alias = instrValue.value;
37 + break;
38 + }
39 case "ComputedLoad":
40 case "PropertyLoad": {
41 alias = instrValue.object;
@@ -53,5 +49,5 @@ function inferInstr(instr: Instruction, state: AliasAnalyser) {
49 return;
50 }
51
56 - state.alias(lvalue, alias);
52 + aliases.union([lvalue.place.identifier, alias.identifier]);
53 }
compiler/forget/src/Inference/InferAliasForStores.ts
+3
@@ -24,6 +24,9 @@ export function inferAliasForStores(
24 if (lvalue.place.effect !== Effect.Store) {
25 continue;
26 }
27 + if (value.kind === "StoreLocal") {
28 + maybeAlias(aliases, value.lvalue.place, value.value, instr.id);
29 + }
30 for (const operand of eachInstructionValueOperand(value)) {
31 if (
32 operand.effect === Effect.Capture ||
compiler/forget/src/Inference/InferMutableLifetimes.ts
+9 -2
@@ -118,8 +118,15 @@ export function inferMutableLifetimes(
118 }
119
120 for (const instr of block.instructions) {
121 - for (const input of eachInstructionOperand(instr)) {
122 - inferPlace(input, instr, inferMutableRangeForStores);
121 + if (instr.value.kind === "StoreLocal") {
122 + inferPlace(instr.value.value, instr, inferMutableRangeForStores);
123 + instr.value.lvalue.place.identifier.mutableRange.start = instr.id;
124 + instr.value.lvalue.place.identifier.mutableRange.end =
125 + makeInstructionId(instr.id + 1);
126 + } else {
127 + for (const input of eachInstructionOperand(instr)) {
128 + inferPlace(input, instr, inferMutableRangeForStores);
129 + }
130 }
131
132 const lvalueId = instr.lvalue.place.identifier;
compiler/forget/src/Inference/InferReferenceEffects.ts
+17 -2
@@ -307,9 +307,9 @@ class InferenceState {
307 }
308 case Effect.Capture: {
309 if (
310 + valueKind === ValueKind.Immutable ||
311 valueKind === ValueKind.Frozen ||
311 - valueKind === ValueKind.MaybeFrozen ||
312 - valueKind === ValueKind.Immutable
312 + valueKind === ValueKind.MaybeFrozen
313 ) {
314 effect = Effect.Read;
315 } else {
@@ -790,6 +790,21 @@ function inferBlock(
790 state.alias(lvalue.place, instrValue.place);
791 continue;
792 }
793 + case "StoreLocal": {
794 + const effect =
795 + state.isDefined(instrValue.lvalue.place) &&
796 + state.kind(instrValue.lvalue.place) === ValueKind.Context
797 + ? Effect.Mutate
798 + : Effect.Capture;
799 + state.reference(instrValue.value, effect);
800 +
801 + const lvalue = instr.lvalue;
802 + state.alias(lvalue.place, instrValue.value);
803 + lvalue.place.effect = Effect.Store;
804 + state.alias(instrValue.lvalue.place, instrValue.value);
805 + instrValue.lvalue.place.effect = Effect.Store;
806 + continue;
807 + }
808 default: {
809 assertExhaustive(instrValue, "Unexpected instruction kind");
810 }
compiler/forget/src/Optimization/ConstantPropagation.ts
+8
@@ -313,6 +313,14 @@ function evaluateInstruction(
313 case "LoadLocal": {
314 return read(constants, value.place);
315 }
316 + case "StoreLocal": {
317 + const placeValue = read(constants, value.value);
318 + if (placeValue !== null) {
319 + constants.set(value.lvalue.place.identifier.id, placeValue);
320 + }
321 + // NOTE: always return null to avoid replacing the StoreLocal with its value
322 + return null;
323 + }
324 default: {
325 // TODO: handle more cases
326 return null;
compiler/forget/src/Optimization/DeadCodeElimination.ts
+9 -2
@@ -40,7 +40,7 @@ export function deadCodeElimination(fn: HIRFunction): void {
40 const instr = block.instructions[i]!;
41 if (
42 !used.has(instr.lvalue.place.identifier) &&
43 - pruneableValue(instr.value) &&
43 + pruneableValue(instr.value, used) &&
44 // Can't prune the last value of a value block, that's its value!
45 !(block.kind !== "block" && i === block.instructions.length - 1)
46 ) {
@@ -76,8 +76,15 @@ export function deadCodeElimination(fn: HIRFunction): void {
76 * Returns true if it is safe to prune an instruction with the given value.
77 * Functions which may have side-
78 */
79 -function pruneableValue(value: InstructionValue): boolean {
79 +function pruneableValue(
80 + value: InstructionValue,
81 + used: Set<Identifier>
82 +): boolean {
83 switch (value.kind) {
84 + case "StoreLocal": {
85 + // Stores are pruneable only if the identifier being stored to is never read later
86 + return !used.has(value.lvalue.place.identifier);
87 + }
88 case "CallExpression":
89 case "ComputedCall":
90 case "ComputedStore":
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+50 -21
@@ -99,11 +99,7 @@ function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement {
99 for (const item of block) {
100 switch (item.kind) {
101 case "instruction": {
102 - const statement = codegenInstructionNullable(
103 - cx,
104 - item.instruction,
105 - codegenInstructionValue(cx, item.instruction.value)
106 - );
102 + const statement = codegenInstructionNullable(cx, item.instruction);
103 if (statement !== null) {
104 statements.push(statement);
105 }
@@ -359,23 +355,47 @@ function codegenTerminal(
355
356 function codegenInstructionNullable(
357 cx: Context,
362 - instr: ReactiveInstruction,
363 - value: t.Expression
358 + instr: ReactiveInstruction
359 ): t.Statement | null {
360 let statement;
366 - if (instr.lvalue !== null && cx.hasDeclared(instr.lvalue.place.identifier)) {
367 - statement = codegenInstruction(
368 - cx,
369 - {
370 - ...instr,
371 - lvalue: {
372 - ...instr.lvalue,
373 - kind: InstructionKind.Reassign,
374 - },
375 - },
376 - value
377 - );
361 + if (instr.value.kind === "StoreLocal") {
362 + const kind = cx.hasDeclared(instr.value.lvalue.place.identifier)
363 + ? InstructionKind.Reassign
364 + : instr.value.lvalue.kind;
365 + const value = codegenPlace(cx, instr.value.value);
366 + switch (kind) {
367 + case InstructionKind.Const: {
368 + return createVariableDeclaration(instr.loc, "const", [
369 + t.variableDeclarator(
370 + convertIdentifier(instr.value.lvalue.place.identifier),
371 + value
372 + ),
373 + ]);
374 + }
375 + case InstructionKind.Let: {
376 + return createVariableDeclaration(instr.loc, "let", [
377 + t.variableDeclarator(
378 + convertIdentifier(instr.value.lvalue.place.identifier),
379 + value
380 + ),
381 + ]);
382 + }
383 + case InstructionKind.Reassign: {
384 + return createExpressionStatement(
385 + instr.loc,
386 + t.assignmentExpression(
387 + "=",
388 + convertIdentifier(instr.value.lvalue.place.identifier),
389 + value
390 + )
391 + );
392 + }
393 + default: {
394 + assertExhaustive(kind, `Unexpected instruction kind '${kind}'`);
395 + }
396 + }
397 } else {
398 + const value = codegenInstructionValue(cx, instr.value);
399 statement = codegenInstruction(cx, instr, value);
400 }
401 if (statement.type === "EmptyStatement") {
@@ -473,7 +493,10 @@ function codegenInstruction(
493 cx.temp.set(instr.lvalue.place.identifier.id, value);
494 return t.emptyStatement();
495 } else {
476 - switch (instr.lvalue.kind) {
496 + const kind = cx.hasDeclared(instr.lvalue.place.identifier)
497 + ? InstructionKind.Reassign
498 + : instr.lvalue.kind;
499 + switch (kind) {
500 case InstructionKind.Const: {
501 return createVariableDeclaration(instr.loc, "const", [
502 t.variableDeclarator(codegenLVal(instr.lvalue), value),
@@ -492,7 +515,7 @@ function codegenInstruction(
515 }
516 default: {
517 assertExhaustive(
495 - instr.lvalue.kind,
518 + kind,
519 `Unexpected instruction kind '${instr.lvalue.kind}'`
520 );
521 }
@@ -704,6 +727,12 @@ function codegenInstructionValue(
727 value = codegenPlace(cx, instrValue.place);
728 break;
729 }
730 + case "StoreLocal": {
731 + CompilerError.invariant(
732 + `Unexpected StoreLocal in codegenInstructionValue`,
733 + instrValue.loc
734 + );
735 + }
736 case "FunctionExpression": {
737 value = instrValue.expr;
738 break;
compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts
+40 -31
@@ -21,27 +21,34 @@ import {
21 } from "./visitors";
22
23 type IdentifierReactivity = Map<IdentifierId, boolean>;
24 -class Visitor extends ReactiveFunctionVisitor<IdentifierReactivity> {
25 - override visitInstruction(
26 - instr: ReactiveInstruction,
27 - reactivityMap: IdentifierReactivity
28 - ) {
29 - this.traverseInstruction(instr, reactivityMap);
24 +
25 +class State {
26 + reactivityMap: IdentifierReactivity = new Map();
27 + temporaries: Map<IdentifierId, IdentifierId> = new Map();
28 +}
29 +
30 +class Visitor extends ReactiveFunctionVisitor<State> {
31 + override visitInstruction(instr: ReactiveInstruction, state: State) {
32 + this.traverseInstruction(instr, state);
33 const lval = instr.lvalue;
34 if (lval == null) {
35 return;
36 }
37 const { value } = instr;
35 - let hasReactiveInput = reactivityMap.get(lval.place.identifier.id) === true;
36 - if (!hasReactiveInput && value.kind !== "LoadGlobal") {
37 - for (const operand of eachReactiveValueOperand(value)) {
38 - // We currently treat free variables (from module or global scope) as
39 - // non-reactive. We may later want type information about specific
40 - // free variables, or a toggle `treatFreeVarsAsReactive`.
41 - if (reactivityMap.get(operand.identifier.id)) {
42 - hasReactiveInput = true;
43 - break;
44 - }
38 + let hasReactiveInput = false;
39 + // Globals are currently treated as non-reactive this happens implicitly because LoadGlobal
40 + // has no operands which can be registered as reactive.
41 + // Consider adding an option to declare whether a given global can be reactive or not, or
42 + // a more general "treat all globals as reactive" flag.
43 + for (const operand of eachReactiveValueOperand(value)) {
44 + if (operand.effect === Effect.Store) {
45 + continue;
46 + }
47 + const resolvedId: IdentifierId =
48 + state.temporaries.get(operand.identifier.id) ?? operand.identifier.id;
49 + if (state.reactivityMap.get(resolvedId)) {
50 + hasReactiveInput = true;
51 + break;
52 }
53 }
54 if (
@@ -56,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor<IdentifierReactivity> {
63 // allow treating safe hooks as non-reactive.
64 hasReactiveInput = true;
65 }
59 - reactivityMap.set(lval.place.identifier.id, hasReactiveInput);
66 + state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput);
67
68 if (hasReactiveInput) {
69 // all mutating effects must also be marked as reactive
@@ -65,12 +72,10 @@ class Visitor extends ReactiveFunctionVisitor<IdentifierReactivity> {
72 case Effect.Capture:
73 case Effect.Store:
74 case Effect.Mutate: {
68 - // Explicitly compare to `false` here, since absence from the
69 - // map indicates a free variable
70 - // todo [@mofeiZ] add knowledge about free variables
71 - if (reactivityMap.get(operand.identifier.id) === false) {
72 - reactivityMap.set(operand.identifier.id, true);
73 - }
75 + const resolvedId: IdentifierId =
76 + state.temporaries.get(operand.identifier.id) ??
77 + operand.identifier.id;
78 + state.reactivityMap.set(resolvedId, true);
79 break;
80 }
81 case Effect.Freeze:
@@ -90,6 +95,14 @@ class Visitor extends ReactiveFunctionVisitor<IdentifierReactivity> {
95 }
96 }
97 }
98 + if (instr.lvalue !== null) {
99 + if (instr.value.kind === "LoadLocal") {
100 + state.temporaries.set(
101 + instr.lvalue.place.identifier.id,
102 + instr.value.place.identifier.id
103 + );
104 + }
105 + }
106 }
107 }
108 /**
@@ -134,18 +147,14 @@ export function inferReactiveIdentifiers(
147 fn: ReactiveFunction
148 ): Set<IdentifierId> {
149 const visitor = new Visitor();
137 - const reactivityMap: IdentifierReactivity = new Map();
150 + const state = new State();
151 for (const param of fn.params) {
139 - reactivityMap.set(param.identifier.id, true);
152 + state.reactivityMap.set(param.identifier.id, true);
153 }
141 - let size: number;
142 - do {
143 - size = reactivityMap.size;
144 - visitReactiveFunction(fn, visitor, reactivityMap);
145 - } while (reactivityMap.size > size);
154 + visitReactiveFunction(fn, visitor, state);
155
156 const result = new Set<IdentifierId>();
148 - reactivityMap.forEach((isReactive, id) => {
157 + state.reactivityMap.forEach((isReactive, id) => {
158 if (isReactive) result.add(id);
159 });
160 return result;
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+22 -6
@@ -102,14 +102,29 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
102 if (range.end > range.start + 1 || mayAllocate(instr.value)) {
103 operands.push(instr.lvalue!.place.identifier);
104 }
105 - for (const operand of eachInstructionOperand(instr)) {
105 + if (instr.value.kind === "StoreLocal") {
106 if (
107 - isMutable(instr, operand) &&
108 - // exclude global variables from being added to scopes, we can't recreate them!
109 - // TODO: improve handling of module-scoped variables and globals
110 - operand.identifier.mutableRange.start > 0
107 + instr.value.lvalue.place.identifier.mutableRange.end >
108 + instr.value.lvalue.place.identifier.mutableRange.start + 1
109 ) {
112 - operands.push(operand.identifier);
110 + operands.push(instr.value.lvalue.place.identifier);
111 + }
112 + if (
113 + isMutable(instr, instr.value.value) &&
114 + instr.value.value.identifier.mutableRange.start > 0
115 + ) {
116 + operands.push(instr.value.value.identifier);
117 + }
118 + } else {
119 + for (const operand of eachInstructionOperand(instr)) {
120 + if (
121 + isMutable(instr, operand) &&
122 + // exclude global variables from being added to scopes, we can't recreate them!
123 + // TODO: improve handling of module-scoped variables and globals
124 + operand.identifier.mutableRange.start > 0
125 + ) {
126 + operands.push(operand.identifier);
127 + }
128 }
129 }
130 if (operands.length !== 0) {
@@ -168,6 +183,7 @@ function isMutable({ id }: Instruction, place: Place): boolean {
183
184 function mayAllocate(value: InstructionValue): boolean {
185 switch (value.kind) {
186 + case "StoreLocal":
187 case "LoadGlobal":
188 case "TypeCastExpression":
189 case "BinaryExpression":
compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+33 -26
@@ -522,18 +522,15 @@ class Context {
522 * Record a variable that is declared in some other scope and that is being reassigned in the
523 * current one as a {@link ReactiveScope.reassignments}
524 */
525 - visitReassignment(lvalue: LValue): void {
526 - if (lvalue.kind !== InstructionKind.Reassign) {
527 - return;
528 - }
529 - const declaration = this.#declarations.get(lvalue.place.identifier.id);
525 + visitReassignment(place: Place): void {
526 + const declaration = this.#declarations.get(place.identifier.id);
527 if (
528 this.currentScope != null &&
532 - lvalue.place.identifier.scope != null &&
529 + place.identifier.scope != null &&
530 declaration !== undefined &&
534 - declaration.scope !== lvalue.place.identifier.scope
531 + declaration.scope !== place.identifier.scope
532 ) {
536 - this.currentScope.reassignments.add(lvalue.place.identifier);
533 + this.currentScope.reassignments.add(place.identifier);
534 }
535 }
536 }
@@ -570,21 +567,21 @@ function visit(context: Context, block: ReactiveBlock): void {
567 break;
568 }
569 case "for": {
573 - visitReactiveValue(context, terminal.init);
574 - visitReactiveValue(context, terminal.test);
570 + visitReactiveValue(context, terminal.id, terminal.init);
571 + visitReactiveValue(context, terminal.id, terminal.test);
572 context.enterConditional(() => {
576 - visitReactiveValue(context, terminal.update);
573 + visitReactiveValue(context, terminal.id, terminal.update);
574 visit(context, terminal.loop);
575 });
576 break;
577 }
578 case "do-while": {
579 visit(context, terminal.loop);
583 - visitReactiveValue(context, terminal.test);
580 + visitReactiveValue(context, terminal.id, terminal.test);
581 break;
582 }
583 case "while": {
587 - visitReactiveValue(context, terminal.test);
584 + visitReactiveValue(context, terminal.id, terminal.test);
585 context.enterConditional(() => {
586 visit(context, terminal.loop);
587 });
@@ -642,22 +639,25 @@ function visit(context: Context, block: ReactiveBlock): void {
639 }
640 }
641
645 -function visitReactiveValue(context: Context, value: ReactiveValue): void {
642 +function visitReactiveValue(
643 + context: Context,
644 + id: InstructionId,
645 + value: ReactiveValue
646 +): void {
647 switch (value.kind) {
648 case "LogicalExpression": {
648 - visitReactiveValue(context, value.left);
649 -
649 + visitReactiveValue(context, id, value.left);
650 context.enterConditional(() => {
651 - visitReactiveValue(context, value.right);
651 + visitReactiveValue(context, id, value.right);
652 });
653 break;
654 }
655 case "ConditionalExpression": {
656 - visitReactiveValue(context, value.test);
656 + visitReactiveValue(context, id, value.test);
657
658 context.enterConditional(() => {
659 - visitReactiveValue(context, value.consequent);
660 - visitReactiveValue(context, value.alternate);
659 + visitReactiveValue(context, id, value.consequent);
660 + visitReactiveValue(context, id, value.alternate);
661 });
662 break;
663 }
@@ -665,7 +665,7 @@ function visitReactiveValue(context: Context, value: ReactiveValue): void {
665 for (const instr of value.instructions) {
666 visitInstruction(context, instr);
667 }
668 - visitInstructionValue(context, value.value, null);
668 + visitInstructionValue(context, id, value.value, null);
669 break;
670 }
671 default: {
@@ -678,6 +678,7 @@ function visitReactiveValue(context: Context, value: ReactiveValue): void {
678
679 function visitInstructionValue(
680 context: Context,
681 + id: InstructionId,
682 value: ReactiveValue,
683 lvalue: LValue | null
684 ): void {
@@ -696,20 +697,26 @@ function visitInstructionValue(
697 } else {
698 context.visitProperty(value.object, value.property);
699 }
700 + } else if (value.kind === "StoreLocal") {
701 + context.visitOperand(value.value);
702 + if (value.lvalue.kind === InstructionKind.Reassign) {
703 + context.visitReassignment(value.lvalue.place);
704 + }
705 + context.declare(value.lvalue.place.identifier, {
706 + id,
707 + scope: context.currentScope,
708 + });
709 } else {
700 - visitReactiveValue(context, value);
710 + visitReactiveValue(context, id, value);
711 }
712 }
713
714 function visitInstruction(context: Context, instr: ReactiveInstruction): void {
715 const { lvalue } = instr;
706 - visitInstructionValue(context, instr.value, lvalue);
716 + visitInstructionValue(context, instr.id, instr.value, lvalue);
717 if (lvalue == null) {
718 return;
719 }
710 - if (lvalue.kind === InstructionKind.Reassign) {
711 - context.visitReassignment(lvalue);
712 - }
720 context.declare(lvalue.place.identifier, {
721 id: instr.id,
722 scope: context.currentScope,
compiler/forget/src/SSA/EnterSSA.ts
+10 -1
@@ -212,7 +212,16 @@ export default function enterSSA(func: HIRFunction): void {
212 }
213
214 for (const instr of block.instructions) {
215 - mapInstructionOperands(instr, (place) => builder.getPlace(place));
215 + if (instr.value.kind === "StoreLocal") {
216 + const oldPlace = instr.value.lvalue.place;
217 + const newPlace = builder.definePlace(oldPlace);
218 + instr.lvalue.kind = InstructionKind.Const;
219 + instr.value.lvalue.place = newPlace;
220 +
221 + instr.value.value = builder.getPlace(instr.value.value);
222 + } else {
223 + mapInstructionOperands(instr, (place) => builder.getPlace(place));
224 + }
225
226 const oldPlace = instr.lvalue.place;
227 const newPlace = builder.definePlace(oldPlace);
compiler/forget/src/SSA/LeaveSSA.ts
+89 -26
@@ -110,7 +110,7 @@ export function leaveSSA(fn: HIRFunction): void {
110 for (const instr of block.instructions) {
111 // Iterate the instructions and perform any rewrites as well as promoting SSA variables to
112 // `let` or `reassign` where possible.
113 - const { lvalue } = instr;
113 + const { lvalue, value } = instr;
114 if (
115 lvalue.kind === InstructionKind.Const &&
116 rewrites.has(lvalue.place.identifier)
@@ -122,16 +122,30 @@ export function leaveSSA(fn: HIRFunction): void {
122 rewrites.get(lvalue.place.identifier) === lvalue.place.identifier
123 ? InstructionKind.Let
124 : InstructionKind.Reassign;
125 - } else if (lvalue.place.identifier.name != null) {
126 - const originalLVal = declarations.get(lvalue.place.identifier.name);
125 + } else if (
126 + value.kind === "StoreLocal" &&
127 + value.lvalue.place.identifier.name != null
128 + ) {
129 + const originalLVal = declarations.get(
130 + value.lvalue.place.identifier.name
131 + );
132 if (originalLVal === undefined) {
128 - declarations.set(lvalue.place.identifier.name, lvalue);
133 + declarations.set(value.lvalue.place.identifier.name, value.lvalue);
134 + value.lvalue.kind = InstructionKind.Const;
135 } else {
136 // This is an instance of the original id, so we need to promote the original declaration
137 // to a `let` and the current lval to a `reassign`
138 originalLVal.kind = InstructionKind.Let;
133 - lvalue.kind = InstructionKind.Reassign;
139 }
140 + } else if (
141 + value.kind === "StoreLocal" &&
142 + rewrites.has(value.lvalue.place.identifier)
143 + ) {
144 + value.lvalue.kind =
145 + rewrites.get(value.lvalue.place.identifier) ===
146 + value.lvalue.place.identifier
147 + ? InstructionKind.Let
148 + : InstructionKind.Reassign;
149 }
150 rewritePlace(lvalue.place, rewrites, declarations);
151 for (const operand of eachInstructionValueOperand(instr.value)) {
@@ -223,6 +237,58 @@ export function leaveSSA(fn: HIRFunction): void {
237 );
238 const declaration = declarations.get(phi.id.name);
239 if (declaration === undefined) {
240 + let initValue: Place;
241 + if (initOperand === null) {
242 + initValue = {
243 + effect: Effect.Read,
244 + kind: "Identifier",
245 + loc: GeneratedSource,
246 + identifier: {
247 + id: fn.env.nextIdentifierId,
248 + name: null,
249 + mutableRange: {
250 + // TODO: this is technically the wrong start range; we do this because the instruction to create the
251 + // undefined and the instruction to store it to the identifier share an InstructionId, which makes
252 + // this value otherwise appear mutable when stored. All that matters is that the range end prior
253 + // to the StoreLocal's instruction id, so we decrement by one.
254 + start: makeInstructionId(block.terminal.id - 1),
255 + end: makeInstructionId(block.terminal.id),
256 + },
257 + scope: null,
258 + type: { kind: "Primitive" },
259 + },
260 + };
261 + block.instructions.push({
262 + id: block.terminal.id,
263 + lvalue: {
264 + place: { ...initValue, effect: Effect.Mutate },
265 + kind: InstructionKind.Const,
266 + },
267 + value: {
268 + kind: "Primitive",
269 + // TODO: consider leaving the variable uninitialized rather than explicitly undefined.
270 + value: undefined,
271 + loc: GeneratedSource,
272 + },
273 + loc: GeneratedSource,
274 + });
275 + } else {
276 + initValue = {
277 + kind: "Identifier",
278 + identifier: initOperand,
279 + effect: Effect.Capture,
280 + loc: GeneratedSource,
281 + };
282 + }
283 + const lvalue: LValue = {
284 + place: {
285 + kind: "Identifier",
286 + identifier: phi.id,
287 + effect: Effect.Mutate,
288 + loc: GeneratedSource,
289 + },
290 + kind: InstructionKind.Let,
291 + };
292 const instr: Instruction = {
293 // NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway.
294 // the mutable range of this canonical id must by definition span from the binding (before
@@ -231,34 +297,31 @@ export function leaveSSA(fn: HIRFunction): void {
297 lvalue: {
298 place: {
299 kind: "Identifier",
234 - identifier: phi.id,
300 + identifier: {
301 + id: fn.env.nextIdentifierId,
302 + mutableRange: {
303 + start: block.terminal.id,
304 + end: makeInstructionId(block.terminal.id + 1),
305 + },
306 + name: null,
307 + scope: null,
308 + type: phi.id.type,
309 + },
310 effect: Effect.Mutate,
311 loc: GeneratedSource,
312 },
238 - kind: InstructionKind.Let,
313 + kind: InstructionKind.Const,
314 + },
315 + value: {
316 + kind: "StoreLocal",
317 + lvalue,
318 + value: initValue,
319 + loc: GeneratedSource,
320 },
240 - value:
241 - initOperand !== null
242 - ? {
243 - kind: "LoadLocal",
244 - place: {
245 - kind: "Identifier",
246 - identifier: initOperand,
247 - effect: Effect.Read,
248 - loc: GeneratedSource,
249 - },
250 - loc: GeneratedSource,
251 - }
252 - : {
253 - kind: "Primitive",
254 - // TODO: consider leaving the variable uninitialized rather than explicitly undefined.
255 - value: undefined,
256 - loc: GeneratedSource,
257 - },
321 loc: GeneratedSource,
322 };
323 block.instructions.push(instr);
261 - declarations.set(phi.id.name, instr.lvalue);
324 + declarations.set(phi.id.name, lvalue);
325 phi.id.mutableRange.start = terminal.id;
326 if (!isPhiMutatedAfterCreation) {
327 phi.id.mutableRange.end = makeInstructionId(terminal.id + 1);
compiler/forget/src/TypeInference/InferTypes.ts
+9
@@ -112,6 +112,15 @@ function* generateInstructionTypes(
112 break;
113 }
114
115 + case "StoreLocal": {
116 + yield equation(left, value.value.identifier.type);
117 + yield equation(
118 + value.lvalue.place.identifier.type,
119 + value.value.identifier.type
120 + );
121 + break;
122 + }
123 +
124 case "BinaryExpression": {
125 if (isPrimitiveBinaryOp(value.operator)) {
126 yield equation(value.left.identifier.type, { kind: "Primitive" });
compiler/forget/src/__tests__/fixtures/hir/_bug.capturing-func-simple-alias.expect.md
+5 -4
@@ -20,14 +20,15 @@ function component(a) {
20 function component(a) {
21 const $ = React.unstable_useMemoCache(2);
22 const c_0 = $[0] !== a;
23 - let x;
23 + let t0;
24 if (c_0) {
25 - x = { a: a };
25 + t0 = { a: a };
26 $[0] = a;
27 - $[1] = x;
27 + $[1] = t0;
28 } else {
29 - x = $[1];
29 + t0 = $[1];
30 }
31 + const x = t0;
32
33 (function () {
34 y = x;
compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md
+5 -4
@@ -18,13 +18,14 @@ function component() {
18 ```javascript
19 function component() {
20 const $ = React.unstable_useMemoCache(3);
21 - let z;
21 + let t0;
22 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
23 - z = [];
24 - $[0] = z;
23 + t0 = [];
24 + $[0] = t0;
25 } else {
26 - z = $[0];
26 + t0 = $[0];
27 }
28 + const z = t0;
29 let y;
30 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
31 y = {};
compiler/forget/src/__tests__/fixtures/hir/allocating-primitive-as-dep.expect.md
+32 -27
@@ -41,63 +41,68 @@ function AllocatingPrimitiveAsDep(props) {
41 }
42 const t1 = t0.b + 1;
43 const c_2 = $[2] !== t1;
44 - let y;
44 + let t2;
45 if (c_2) {
46 - y = foo(t1);
46 + t2 = foo(t1);
47 $[2] = t1;
48 - $[3] = y;
48 + $[3] = t2;
49 } else {
50 - y = $[3];
50 + t2 = $[3];
51 }
52 + const y = t2;
53 return y;
54 }
55
56 function PrimitiveAsDepNested(props) {
56 - const $ = React.unstable_useMemoCache(10);
57 + const $ = React.unstable_useMemoCache(11);
58 const c_0 = $[0] !== props.b;
59 const c_1 = $[1] !== props.a;
60 let x;
61 + let y;
62 if (c_0 || c_1) {
63 x = {};
64 mutate(x);
63 - const c_3 = $[3] !== props.b;
65 + const c_4 = $[4] !== props.b;
66 let t0;
65 - if (c_3) {
67 + if (c_4) {
68 t0 = bar(props.b);
67 - $[3] = props.b;
68 - $[4] = t0;
69 + $[4] = props.b;
70 + $[5] = t0;
71 } else {
70 - t0 = $[4];
72 + t0 = $[5];
73 }
74 const t1 = t0 + 1;
73 - const c_5 = $[5] !== t1;
74 - let y;
75 - if (c_5) {
76 - y = foo(t1);
77 - $[5] = t1;
78 - $[6] = y;
75 + const c_6 = $[6] !== t1;
76 + let t2;
77 + if (c_6) {
78 + t2 = foo(t1);
79 + $[6] = t1;
80 + $[7] = t2;
81 } else {
80 - y = $[6];
82 + t2 = $[7];
83 }
84 + y = t2;
85 mutate(x, props.a);
86 $[0] = props.b;
87 $[1] = props.a;
88 $[2] = x;
89 + $[3] = y;
90 } else {
91 x = $[2];
92 + y = $[3];
93 }
89 - const c_7 = $[7] !== x;
90 - const c_8 = $[8] !== y;
91 - let t2;
92 - if (c_7 || c_8) {
93 - t2 = [x, y];
94 - $[7] = x;
95 - $[8] = y;
96 - $[9] = t2;
94 + const c_8 = $[8] !== x;
95 + const c_9 = $[9] !== y;
96 + let t3;
97 + if (c_8 || c_9) {
98 + t3 = [x, y];
99 + $[8] = x;
100 + $[9] = y;
101 + $[10] = t3;
102 } else {
98 - t2 = $[9];
103 + t3 = $[10];
104 }
100 - return t2;
105 + return t3;
106 }
107
108 ```
compiler/forget/src/__tests__/fixtures/hir/array-access-assignment.expect.md
+10 -9
@@ -26,14 +26,15 @@ function foo(a, b, c) {
26 if (c_0 || c_1 || c_2) {
27 x = [a];
28 const c_5 = $[5] !== b;
29 - let y;
29 + let t0;
30 if (c_5) {
31 - y = [null, b];
31 + t0 = [null, b];
32 $[5] = b;
33 - $[6] = y;
33 + $[6] = t0;
34 } else {
35 - y = $[6];
35 + t0 = $[6];
36 }
37 + const y = t0;
38 z = [[], [], [c]];
39 x[0] = y[1];
40 z[0][0] = x[0];
@@ -48,16 +49,16 @@ function foo(a, b, c) {
49 }
50 const c_7 = $[7] !== x;
51 const c_8 = $[8] !== z;
51 - let t0;
52 + let t1;
53 if (c_7 || c_8) {
53 - t0 = [x, z];
54 + t1 = [x, z];
55 $[7] = x;
56 $[8] = z;
56 - $[9] = t0;
57 + $[9] = t1;
58 } else {
58 - t0 = $[9];
59 + t1 = $[9];
60 }
60 - return t0;
61 + return t1;
62 }
63
64 ```
compiler/forget/src/__tests__/fixtures/hir/assignment-in-nested-if.expect.md
+5 -3
@@ -24,12 +24,14 @@ function useBar(props) {
24 let z = undefined;
25 if (props.a) {
26 if (props.b) {
27 + let t0;
28 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28 - z = baz();
29 - $[0] = z;
29 + t0 = baz();
30 + $[0] = t0;
31 } else {
31 - z = $[0];
32 + t0 = $[0];
33 }
34 + z = t0;
35 }
36 }
37 return z;
compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md
+1 -2
@@ -16,8 +16,7 @@ function f() {
16
17 ```javascript
18 function f() {
19 - let x = 3;
20 - x = x >>> 1;
19 + const x = 3 >>> 1;
20 return x;
21 }
22
compiler/forget/src/__tests__/fixtures/hir/bug_object-pattern.expect.md
+5 -4
@@ -17,14 +17,15 @@ function component(t) {
17 const $ = React.unstable_useMemoCache(2);
18 const a = t.a;
19 const c_0 = $[0] !== a;
20 - let y;
20 + let t0;
21 if (c_0) {
22 - y = { a: a };
22 + t0 = { a: a };
23 $[0] = a;
24 - $[1] = y;
24 + $[1] = t0;
25 } else {
26 - y = $[1];
26 + t0 = $[1];
27 }
28 + const y = t0;
29 return y;
30 }
31
compiler/forget/src/__tests__/fixtures/hir/capture-func-passed-to-jsx.expect.md
+20 -16
@@ -22,46 +22,50 @@ function component(a, b) {
22 function component(a, b) {
23 const $ = React.unstable_useMemoCache(9);
24 const c_0 = $[0] !== b;
25 - let y;
25 + let t0;
26 if (c_0) {
27 - y = { b: b };
27 + t0 = { b: b };
28 $[0] = b;
29 - $[1] = y;
29 + $[1] = t0;
30 } else {
31 - y = $[1];
31 + t0 = $[1];
32 }
33 + const y = t0;
34 const c_2 = $[2] !== a;
34 - let z;
35 + let t1;
36 if (c_2) {
36 - z = { a: a };
37 + t1 = { a: a };
38 $[2] = a;
38 - $[3] = z;
39 + $[3] = t1;
40 } else {
40 - z = $[3];
41 + t1 = $[3];
42 }
43 + const z = t1;
44 const c_4 = $[4] !== z.a;
45 const c_5 = $[5] !== y.b;
44 - let x;
46 + let t2;
47 if (c_4 || c_5) {
46 - x = function () {
48 + t2 = function () {
49 z.a = 2;
50 y.b;
51 };
52 $[4] = z.a;
53 $[5] = y.b;
52 - $[6] = x;
54 + $[6] = t2;
55 } else {
54 - x = $[6];
56 + t2 = $[6];
57 }
58 + const x = t2;
59 const c_7 = $[7] !== x;
57 - let t;
60 + let t3;
61 if (c_7) {
59 - t = <Foo x={x}></Foo>;
62 + t3 = <Foo x={x}></Foo>;
63 $[7] = x;
61 - $[8] = t;
64 + $[8] = t3;
65 } else {
63 - t = $[8];
66 + t3 = $[8];
67 }
68 + const t = t3;
69 mutate(x);
70 return t;
71 }
compiler/forget/src/__tests__/fixtures/hir/capturing-arrow-function-1.expect.md
+10 -8
@@ -18,25 +18,27 @@ function component(a) {
18 function component(a) {
19 const $ = React.unstable_useMemoCache(4);
20 const c_0 = $[0] !== a;
21 - let z;
21 + let t0;
22 if (c_0) {
23 - z = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = z;
25 + $[1] = t0;
26 } else {
27 - z = $[1];
27 + t0 = $[1];
28 }
29 + const z = t0;
30 const c_2 = $[2] !== z;
30 - let x;
31 + let t1;
32 if (c_2) {
32 - x = () => {
33 + t1 = () => {
34 z;
35 };
36 $[2] = z;
36 - $[3] = x;
37 + $[3] = t1;
38 } else {
38 - x = $[3];
39 + t1 = $[3];
40 }
41 + const x = t1;
42 return x;
43 }
44
compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-2.expect.md
+5 -4
@@ -21,14 +21,15 @@ function component(a, b) {
21 function component(a, b) {
22 const $ = React.unstable_useMemoCache(5);
23 const c_0 = $[0] !== b;
24 - let y;
24 + let t0;
25 if (c_0) {
26 - y = { b: b };
26 + t0 = { b: b };
27 $[0] = b;
28 - $[1] = y;
28 + $[1] = t0;
29 } else {
30 - y = $[1];
30 + t0 = $[1];
31 }
32 + const y = t0;
33 const c_2 = $[2] !== a;
34 const c_3 = $[3] !== y.b;
35 let x;
compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate-3.expect.md
+15 -12
@@ -20,37 +20,40 @@ function component(a, b) {
20 function component(a, b) {
21 const $ = React.unstable_useMemoCache(7);
22 const c_0 = $[0] !== b;
23 - let y;
23 + let t0;
24 if (c_0) {
25 - y = { b: b };
25 + t0 = { b: b };
26 $[0] = b;
27 - $[1] = y;
27 + $[1] = t0;
28 } else {
29 - y = $[1];
29 + t0 = $[1];
30 }
31 + const y = t0;
32 const c_2 = $[2] !== a;
32 - let z;
33 + let t1;
34 if (c_2) {
34 - z = { a: a };
35 + t1 = { a: a };
36 $[2] = a;
36 - $[3] = z;
37 + $[3] = t1;
38 } else {
38 - z = $[3];
39 + t1 = $[3];
40 }
41 + const z = t1;
42 const c_4 = $[4] !== z.a;
43 const c_5 = $[5] !== y.b;
42 - let x;
44 + let t2;
45 if (c_4 || c_5) {
44 - x = function () {
46 + t2 = function () {
47 z.a = 2;
48 y.b;
49 };
50 $[4] = z.a;
51 $[5] = y.b;
50 - $[6] = x;
52 + $[6] = t2;
53 } else {
52 - x = $[6];
54 + t2 = $[6];
55 }
56 + const x = t2;
57 return x;
58 }
59
compiler/forget/src/__tests__/fixtures/hir/capturing-func-mutate.expect.md
+5 -4
@@ -26,14 +26,15 @@ function component(a, b) {
26 if (c_0 || c_1) {
27 const z = { a: a };
28 const c_3 = $[3] !== b;
29 - let y;
29 + let t0;
30 if (c_3) {
31 - y = { b: b };
31 + t0 = { b: b };
32 $[3] = b;
33 - $[4] = y;
33 + $[4] = t0;
34 } else {
35 - y = $[4];
35 + t0 = $[4];
36 }
37 + const y = t0;
38 x = function () {
39 z.a = 2;
40 y.b;
compiler/forget/src/__tests__/fixtures/hir/capturing-function-1.expect.md
+10 -8
@@ -18,25 +18,27 @@ function component(a) {
18 function component(a) {
19 const $ = React.unstable_useMemoCache(4);
20 const c_0 = $[0] !== a;
21 - let z;
21 + let t0;
22 if (c_0) {
23 - z = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = z;
25 + $[1] = t0;
26 } else {
27 - z = $[1];
27 + t0 = $[1];
28 }
29 + const z = t0;
30 const c_2 = $[2] !== z;
30 - let x;
31 + let t1;
32 if (c_2) {
32 - x = function () {
33 + t1 = function () {
34 z;
35 };
36 $[2] = z;
36 - $[3] = x;
37 + $[3] = t1;
38 } else {
38 - x = $[3];
39 + t1 = $[3];
40 }
41 + const x = t1;
42 return x;
43 }
44
compiler/forget/src/__tests__/fixtures/hir/capturing-function-member-expr-call.expect.md
+19 -18
@@ -19,44 +19,45 @@ function component({ mutator }) {
19 ## Code
20
21 ```javascript
22 -function component(t23) {
22 +function component(t28) {
23 const $ = React.unstable_useMemoCache(7);
24 - const t0 = t23;
25 - const mutator = t0.mutator;
24 + const mutator = t28.mutator;
25 const c_0 = $[0] !== mutator;
27 - let poke;
26 + let t0;
27 if (c_0) {
29 - poke = () => {
28 + t0 = () => {
29 mutator.poke();
30 };
31 $[0] = mutator;
33 - $[1] = poke;
32 + $[1] = t0;
33 } else {
35 - poke = $[1];
34 + t0 = $[1];
35 }
37 - const c_2 = $[2] !== t0.mutator.user;
38 - let hide;
36 + const poke = t0;
37 + const c_2 = $[2] !== mutator.user;
38 + let t1;
39 if (c_2) {
40 - hide = () => {
40 + t1 = () => {
41 mutator.user.hide();
42 };
43 - $[2] = t0.mutator.user;
44 - $[3] = hide;
43 + $[2] = mutator.user;
44 + $[3] = t1;
45 } else {
46 - hide = $[3];
46 + t1 = $[3];
47 }
48 + const hide = t1;
49 const c_4 = $[4] !== poke;
50 const c_5 = $[5] !== hide;
50 - let t1;
51 + let t2;
52 if (c_4 || c_5) {
52 - t1 = <Foo poke={poke} hide={hide}></Foo>;
53 + t2 = <Foo poke={poke} hide={hide}></Foo>;
54 $[4] = poke;
55 $[5] = hide;
55 - $[6] = t1;
56 + $[6] = t2;
57 } else {
57 - t1 = $[6];
58 + t2 = $[6];
59 }
59 - return t1;
60 + return t2;
61 }
62
63 ```
compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md
+10 -8
@@ -21,25 +21,27 @@ function component(a) {
21 function component(a) {
22 const $ = React.unstable_useMemoCache(4);
23 const c_0 = $[0] !== a;
24 - let z;
24 + let t0;
25 if (c_0) {
26 - z = { a: a };
26 + t0 = { a: a };
27 $[0] = a;
28 - $[1] = z;
28 + $[1] = t0;
29 } else {
30 - z = $[1];
30 + t0 = $[1];
31 }
32 + const z = t0;
33 const c_2 = $[2] !== z;
33 - let x;
34 + let t1;
35 if (c_2) {
35 - x = function () {
36 + t1 = function () {
37 z;
38 };
39 $[2] = z;
39 - $[3] = x;
40 + $[3] = t1;
41 } else {
41 - x = $[3];
42 + t1 = $[3];
43 }
44 + const x = t1;
45 return x;
46 }
47
compiler/forget/src/__tests__/fixtures/hir/capturing-member-expr.expect.md
+10 -8
@@ -18,25 +18,27 @@ function component(a) {
18 function component(a) {
19 const $ = React.unstable_useMemoCache(4);
20 const c_0 = $[0] !== a;
21 - let z;
21 + let t0;
22 if (c_0) {
23 - z = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = z;
25 + $[1] = t0;
26 } else {
27 - z = $[1];
27 + t0 = $[1];
28 }
29 + const z = t0;
30 const c_2 = $[2] !== z.a;
30 - let x;
31 + let t1;
32 if (c_2) {
32 - x = function () {
33 + t1 = function () {
34 z.a;
35 };
36 $[2] = z.a;
36 - $[3] = x;
37 + $[3] = t1;
38 } else {
38 - x = $[3];
39 + t1 = $[3];
40 }
41 + const x = t1;
42 return x;
43 }
44
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-call.expect.md
+10 -8
@@ -27,25 +27,27 @@ function component(a) {
27 t0 = $[1];
28 }
29 const c_2 = $[2] !== t0;
30 - let z;
30 + let t1;
31 if (c_2) {
32 - z = { a: t0 };
32 + t1 = { a: t0 };
33 $[2] = t0;
34 - $[3] = z;
34 + $[3] = t1;
35 } else {
36 - z = $[3];
36 + t1 = $[3];
37 }
38 + const z = t1;
39 const c_4 = $[4] !== z.a;
39 - let x;
40 + let t2;
41 if (c_4) {
41 - x = function () {
42 + t2 = function () {
43 z.a.a();
44 };
45 $[4] = z.a;
45 - $[5] = x;
46 + $[5] = t2;
47 } else {
47 - x = $[5];
48 + t2 = $[5];
49 }
50 + const x = t2;
51 return x;
52 }
53
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr-in-nested-func.expect.md
+10 -8
@@ -29,27 +29,29 @@ function component(a) {
29 t0 = $[1];
30 }
31 const c_2 = $[2] !== t0;
32 - let z;
32 + let t1;
33 if (c_2) {
34 - z = { a: t0 };
34 + t1 = { a: t0 };
35 $[2] = t0;
36 - $[3] = z;
36 + $[3] = t1;
37 } else {
38 - z = $[3];
38 + t1 = $[3];
39 }
40 + const z = t1;
41 const c_4 = $[4] !== z.a.a;
41 - let x;
42 + let t2;
43 if (c_4) {
43 - x = function () {
44 + t2 = function () {
45 (function () {
46 z.a.a;
47 })();
48 };
49 $[4] = z.a.a;
49 - $[5] = x;
50 + $[5] = t2;
51 } else {
51 - x = $[5];
52 + t2 = $[5];
53 }
54 + const x = t2;
55 return x;
56 }
57
compiler/forget/src/__tests__/fixtures/hir/capturing-nested-member-expr.expect.md
+10 -8
@@ -27,25 +27,27 @@ function component(a) {
27 t0 = $[1];
28 }
29 const c_2 = $[2] !== t0;
30 - let z;
30 + let t1;
31 if (c_2) {
32 - z = { a: t0 };
32 + t1 = { a: t0 };
33 $[2] = t0;
34 - $[3] = z;
34 + $[3] = t1;
35 } else {
36 - z = $[3];
36 + t1 = $[3];
37 }
38 + const z = t1;
39 const c_4 = $[4] !== z.a.a;
39 - let x;
40 + let t2;
41 if (c_4) {
41 - x = function () {
42 + t2 = function () {
43 z.a.a;
44 };
45 $[4] = z.a.a;
45 - $[5] = x;
46 + $[5] = t2;
47 } else {
47 - x = $[5];
48 + t2 = $[5];
49 }
50 + const x = t2;
51 return x;
52 }
53
compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-block.expect.md
+10 -8
@@ -20,27 +20,29 @@ function component(a) {
20 function component(a) {
21 const $ = React.unstable_useMemoCache(4);
22 const c_0 = $[0] !== a;
23 - let z;
23 + let t0;
24 if (c_0) {
25 - z = { a: a };
25 + t0 = { a: a };
26 $[0] = a;
27 - $[1] = z;
27 + $[1] = t0;
28 } else {
29 - z = $[1];
29 + t0 = $[1];
30 }
31 + const z = t0;
32 const c_2 = $[2] !== z;
32 - let x;
33 + let t1;
34 if (c_2) {
34 - x = function () {
35 + t1 = function () {
36 {
37 z;
38 }
39 };
40 $[2] = z;
40 - $[3] = x;
41 + $[3] = t1;
42 } else {
42 - x = $[3];
43 + t1 = $[3];
44 }
45 + const x = t1;
46 return x;
47 }
48
compiler/forget/src/__tests__/fixtures/hir/capturing-variable-in-nested-function.expect.md
+10 -8
@@ -20,27 +20,29 @@ function component(a) {
20 function component(a) {
21 const $ = React.unstable_useMemoCache(4);
22 const c_0 = $[0] !== a;
23 - let z;
23 + let t0;
24 if (c_0) {
25 - z = { a: a };
25 + t0 = { a: a };
26 $[0] = a;
27 - $[1] = z;
27 + $[1] = t0;
28 } else {
29 - z = $[1];
29 + t0 = $[1];
30 }
31 + const z = t0;
32 const c_2 = $[2] !== z;
32 - let x;
33 + let t1;
34 if (c_2) {
34 - x = function () {
35 + t1 = function () {
36 (function () {
37 z;
38 })();
39 };
40 $[2] = z;
40 - $[3] = x;
41 + $[3] = t1;
42 } else {
42 - x = $[3];
43 + t1 = $[3];
44 }
45 + const x = t1;
46 return x;
47 }
48
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+17 -16
@@ -45,14 +45,15 @@ function Component(props) {
45 renderedItems = [];
46 const seen = new Set();
47 const c_3 = $[3] !== maxItems;
48 - let max;
48 + let t0;
49 if (c_3) {
50 - max = Math.max(0, maxItems);
50 + t0 = Math.max(0, maxItems);
51 $[3] = maxItems;
52 - $[4] = max;
52 + $[4] = t0;
53 } else {
54 - max = $[4];
54 + t0 = $[4];
55 }
56 + const max = t0;
57 for (let i = 0; i < items.length; i = i + 1, i) {
58 const item = items.at(i);
59 if (item == null || seen.has(item)) {
@@ -74,31 +75,31 @@ function Component(props) {
75
76 const count = renderedItems.length;
77 const c_5 = $[5] !== count;
77 - let t0;
78 + let t1;
79 if (c_5) {
79 - t0 = <h1>{count} Items</h1>;
80 + t1 = <h1>{count} Items</h1>;
81 $[5] = count;
81 - $[6] = t0;
82 + $[6] = t1;
83 } else {
83 - t0 = $[6];
84 + t1 = $[6];
85 }
85 - const c_7 = $[7] !== t0;
86 + const c_7 = $[7] !== t1;
87 const c_8 = $[8] !== renderedItems;
87 - let t1;
88 + let t2;
89 if (c_7 || c_8) {
89 - t1 = (
90 + t2 = (
91 <div>
91 - {t0}
92 + {t1}
93 {renderedItems}
94 </div>
95 );
95 - $[7] = t0;
96 + $[7] = t1;
97 $[8] = renderedItems;
97 - $[9] = t1;
98 + $[9] = t2;
99 } else {
99 - t1 = $[9];
100 + t2 = $[9];
101 }
101 - return t1;
102 + return t2;
103 }
104
105 ```
compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md
+10 -9
@@ -17,24 +17,25 @@ function component() {
17 const $ = React.unstable_useMemoCache(4);
18 const setX = useState(0)[1];
19 const c_0 = $[0] !== setX;
20 - let handler;
20 + let t0;
21 if (c_0) {
22 - handler = (v) => setX(v);
22 + t0 = (v) => setX(v);
23 $[0] = setX;
24 - $[1] = handler;
24 + $[1] = t0;
25 } else {
26 - handler = $[1];
26 + t0 = $[1];
27 }
28 + const handler = t0;
29 const c_2 = $[2] !== handler;
29 - let t0;
30 + let t1;
31 if (c_2) {
31 - t0 = <Foo handler={handler}></Foo>;
32 + t1 = <Foo handler={handler}></Foo>;
33 $[2] = handler;
33 - $[3] = t0;
34 + $[3] = t1;
35 } else {
35 - t0 = $[3];
36 + t1 = $[3];
37 }
37 - return t0;
38 + return t1;
39 }
40
41 ```
compiler/forget/src/__tests__/fixtures/hir/controlled-input.expect.md
+13 -12
@@ -15,30 +15,31 @@ function component() {
15 ```javascript
16 function component() {
17 const $ = React.unstable_useMemoCache(5);
18 - const t1 = useState(0);
19 - const x = t1[0];
20 - const setX = t1[1];
18 + const t2 = useState(0);
19 + const x = t2[0];
20 + const setX = t2[1];
21 const c_0 = $[0] !== setX;
22 - let handler;
22 + let t0;
23 if (c_0) {
24 - handler = (event) => setX(event.target.value);
24 + t0 = (event) => setX(event.target.value);
25 $[0] = setX;
26 - $[1] = handler;
26 + $[1] = t0;
27 } else {
28 - handler = $[1];
28 + t0 = $[1];
29 }
30 + const handler = t0;
31 const c_2 = $[2] !== handler;
32 const c_3 = $[3] !== x;
32 - let t0;
33 + let t1;
34 if (c_2 || c_3) {
34 - t0 = <input onChange={handler} value={x}></input>;
35 + t1 = <input onChange={handler} value={x}></input>;
36 $[2] = handler;
37 $[3] = x;
37 - $[4] = t0;
38 + $[4] = t1;
39 } else {
39 - t0 = $[4];
40 + t1 = $[4];
41 }
41 - return t0;
42 + return t1;
43 }
44
45 ```
compiler/forget/src/__tests__/fixtures/hir/destructure-capture-global.expect.md
+5 -4
@@ -17,14 +17,15 @@ let someGlobal = {};
17 function component(a) {
18 const $ = React.unstable_useMemoCache(2);
19 const c_0 = $[0] !== a;
20 - let x;
20 + let t0;
21 if (c_0) {
22 - x = { a: a, someGlobal: someGlobal };
22 + t0 = { a: a, someGlobal: someGlobal };
23 $[0] = a;
24 - $[1] = x;
24 + $[1] = t0;
25 } else {
26 - x = $[1];
26 + t0 = $[1];
27 }
28 + const x = t0;
29 return x;
30 }
31
compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md
+2 -2
@@ -32,9 +32,9 @@ function foo(props) {
32 for (
33 let x = 0;
34 x > props.min && x < props.max;
35 - x = x$0 + (props.cond ? props.increment : 2), x
35 + x = x + (props.cond ? props.increment : 2), x
36 ) {
37 - const x$0 = x * 2;
37 + x = x * 2;
38 }
39 return y;
40 }
compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md
+5 -4
@@ -20,13 +20,14 @@ function foo(x) {}
20 ```javascript
21 function Component() {
22 const $ = React.unstable_useMemoCache(1);
23 - let a;
23 + let t0;
24 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - a = [];
26 - $[0] = a;
25 + t0 = [];
26 + $[0] = t0;
27 } else {
28 - a = $[0];
28 + t0 = $[0];
29 }
30 + const a = t0;
31 const b = a;
32 useFreeze(a);
33 foo(b);
compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md
+10 -9
@@ -27,30 +27,31 @@ function foo() {}
27
28 function Component(props) {
29 const $ = React.unstable_useMemoCache(3);
30 - let x;
30 + let t0;
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 - x = [];
33 - $[0] = x;
32 + t0 = [];
33 + $[0] = t0;
34 } else {
35 - x = $[0];
35 + t0 = $[0];
36 }
37 + const x = t0;
38 const y = useFreeze(x);
39 foo(y, x);
40 const c_1 = $[1] !== y;
40 - let t0;
41 + let t1;
42 if (c_1) {
42 - t0 = (
43 + t1 = (
44 <Component>
45 {x}
46 {y}
47 </Component>
48 );
49 $[1] = y;
49 - $[2] = t0;
50 + $[2] = t1;
51 } else {
51 - t0 = $[2];
52 + t1 = $[2];
53 }
53 - return t0;
54 + return t1;
55 }
56
57 ```
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md
+5 -4
@@ -20,13 +20,14 @@ function call(x) {}
20 ```javascript
21 function Component() {
22 const $ = React.unstable_useMemoCache(1);
23 - let a;
23 + let t0;
24 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - a = [];
26 - $[0] = a;
25 + t0 = [];
26 + $[0] = t0;
27 } else {
28 - a = $[0];
28 + t0 = $[0];
29 }
30 + const a = t0;
31 useFreeze(a);
32 useFreeze(a);
33 call(a);
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+5 -3
@@ -33,12 +33,14 @@ function Component(props) {
33 if (cond) {
34 a = x;
35 } else {
36 + let t0;
37 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
37 - a = [];
38 - $[0] = a;
38 + t0 = [];
39 + $[0] = t0;
40 } else {
40 - a = $[0];
41 + t0 = $[0];
42 }
43 + a = t0;
44 }
45
46 useFreeze(a);
compiler/forget/src/__tests__/fixtures/hir/independent.expect.md
+15 -13
@@ -40,35 +40,37 @@ function Foo() {}
40 function Component(props) {
41 const $ = React.unstable_useMemoCache(7);
42 const c_0 = $[0] !== props.a;
43 - let a;
43 + let t0;
44 if (c_0) {
45 - a = compute(props.a);
45 + t0 = compute(props.a);
46 $[0] = props.a;
47 - $[1] = a;
47 + $[1] = t0;
48 } else {
49 - a = $[1];
49 + t0 = $[1];
50 }
51 + const a = t0;
52 const c_2 = $[2] !== props.b;
52 - let b;
53 + let t1;
54 if (c_2) {
54 - b = compute(props.b);
55 + t1 = compute(props.b);
56 $[2] = props.b;
56 - $[3] = b;
57 + $[3] = t1;
58 } else {
58 - b = $[3];
59 + t1 = $[3];
60 }
61 + const b = t1;
62 const c_4 = $[4] !== a;
63 const c_5 = $[5] !== b;
62 - let t0;
64 + let t2;
65 if (c_4 || c_5) {
64 - t0 = <Foo a={a} b={b}></Foo>;
66 + t2 = <Foo a={a} b={b}></Foo>;
67 $[4] = a;
68 $[5] = b;
67 - $[6] = t0;
69 + $[6] = t2;
70 } else {
69 - t0 = $[6];
71 + t2 = $[6];
72 }
71 - return t0;
73 + return t2;
74 }
75
76 function compute() {}
compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md
+15 -12
@@ -24,36 +24,39 @@ function foo(a, b, c) {
24 function foo(a, b, c) {
25 const $ = React.unstable_useMemoCache(8);
26 const c_0 = $[0] !== a;
27 - let x;
27 + let t0;
28 if (c_0) {
29 - x = makeObject(a);
29 + t0 = makeObject(a);
30 $[0] = a;
31 - $[1] = x;
31 + $[1] = t0;
32 } else {
33 - x = $[1];
33 + t0 = $[1];
34 }
35 + const x = t0;
36 const c_2 = $[2] !== a;
36 - let y;
37 + let t1;
38 if (c_2) {
38 - y = makeObject(a);
39 + t1 = makeObject(a);
40 $[2] = a;
40 - $[3] = y;
41 + $[3] = t1;
42 } else {
42 - y = $[3];
43 + t1 = $[3];
44 }
45 + const y = t1;
46 const c_4 = $[4] !== x;
47 const c_5 = $[5] !== y.method;
48 const c_6 = $[6] !== b;
47 - let z;
49 + let t2;
50 if (c_4 || c_5 || c_6) {
49 - z = x[y.method](b);
51 + t2 = x[y.method](b);
52 $[4] = x;
53 $[5] = y.method;
54 $[6] = b;
53 - $[7] = z;
55 + $[7] = t2;
56 } else {
55 - z = $[7];
57 + t2 = $[7];
58 }
59 + const z = t2;
60 return z;
61 }
62
compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md
+10 -8
@@ -21,29 +21,31 @@ function foo(a, b, c) {
21 function foo(a, b, c) {
22 const $ = React.unstable_useMemoCache(6);
23 const c_0 = $[0] !== a;
24 - let x;
24 + let t0;
25 if (c_0) {
26 - x = makeObject(a);
26 + t0 = makeObject(a);
27 $[0] = a;
28 - $[1] = x;
28 + $[1] = t0;
29 } else {
30 - x = $[1];
30 + t0 = $[1];
31 }
32 + const x = t0;
33
34 const method = x.method;
35 const c_2 = $[2] !== method;
36 const c_3 = $[3] !== x;
37 const c_4 = $[4] !== b;
37 - let y;
38 + let t1;
39 if (c_2 || c_3 || c_4) {
39 - y = method.call(x, b);
40 + t1 = method.call(x, b);
41 $[2] = method;
42 $[3] = x;
43 $[4] = b;
43 - $[5] = y;
44 + $[5] = t1;
45 } else {
45 - y = $[5];
46 + t1 = $[5];
47 }
48 + const y = t1;
49 return y;
50 }
51
compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md
+10 -8
@@ -20,25 +20,27 @@ function foo(a, b, c) {
20 function foo(a, b, c) {
21 const $ = React.unstable_useMemoCache(5);
22 const c_0 = $[0] !== a;
23 - let x;
23 + let t0;
24 if (c_0) {
25 - x = makeObject(a);
25 + t0 = makeObject(a);
26 $[0] = a;
27 - $[1] = x;
27 + $[1] = t0;
28 } else {
29 - x = $[1];
29 + t0 = $[1];
30 }
31 + const x = t0;
32 const c_2 = $[2] !== x;
33 const c_3 = $[3] !== b;
33 - let y;
34 + let t1;
35 if (c_2 || c_3) {
35 - y = x.foo(b);
36 + t1 = x.foo(b);
37 $[2] = x;
38 $[3] = b;
38 - $[4] = y;
39 + $[4] = t1;
40 } else {
40 - y = $[4];
41 + t1 = $[4];
42 }
43 + const y = t1;
44 return y;
45 }
46
compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md
+5 -4
@@ -44,13 +44,14 @@ function Component(props) {
44 const $ = React.unstable_useMemoCache(1);
45 const a = {};
46 const b = {};
47 - let c;
47 + let t0;
48 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
49 - c = {};
50 - $[0] = c;
49 + t0 = {};
50 + $[0] = t0;
51 } else {
52 - c = $[0];
52 + t0 = $[0];
53 }
54 + const c = t0;
55 const d = {};
56 while (true) {
57 mutate(a, b);
compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md
+10 -6
@@ -23,22 +23,26 @@ function foo(a, b, c, d) {
23 let x = undefined;
24 if (someVal) {
25 const c_0 = $[0] !== b;
26 + let t0;
27 if (c_0) {
27 - x = { b: b };
28 + t0 = { b: b };
29 $[0] = b;
29 - $[1] = x;
30 + $[1] = t0;
31 } else {
31 - x = $[1];
32 + t0 = $[1];
33 }
34 + x = t0;
35 } else {
36 const c_2 = $[2] !== c;
37 + let t1;
38 if (c_2) {
36 - x = { c: c };
39 + t1 = { c: c };
40 $[2] = c;
38 - $[3] = x;
41 + $[3] = t1;
42 } else {
40 - x = $[3];
43 + t1 = $[3];
44 }
45 + x = t1;
46 }
47 return x;
48 }
compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md
+2 -1
@@ -23,10 +23,11 @@ function foo(a, b, c, d) {
23 ```javascript
24 function foo(a, b, c, d) {
25 const $ = React.unstable_useMemoCache(2);
26 + someObj();
27 const c_0 = $[0] !== a;
28 let x;
29 if (c_0) {
29 - x = someObj();
30 + x = undefined;
31 if (a) {
32 const y = someObj();
33 const z = y;
compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else.expect.md
+2 -1
@@ -21,10 +21,11 @@ function foo(a, b, c, d) {
21 ```javascript
22 function foo(a, b, c, d) {
23 const $ = React.unstable_useMemoCache(2);
24 + someObj();
25 const c_0 = $[0] !== a;
26 let x;
27 if (c_0) {
27 - x = someObj();
28 + x = undefined;
29 if (a) {
30 x = someObj();
31 } else {
compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md
+2 -1
@@ -29,11 +29,12 @@ function foo(a, b, c, d) {
29 ```javascript
30 function foo(a, b, c, d) {
31 const $ = React.unstable_useMemoCache(3);
32 + someObj();
33 const c_0 = $[0] !== a;
34 const c_1 = $[1] !== b;
35 let x;
36 if (c_0 || c_1) {
36 - x = someObj();
37 + x = undefined;
38 if (a) {
39 let z = undefined;
40 if (b) {
compiler/forget/src/__tests__/fixtures/hir/object-pattern-params.expect.md
+18 -16
@@ -13,40 +13,42 @@ function component({ a, b }) {
13 ## Code
14
15 ```javascript
16 -function component(t12) {
16 +function component(t19) {
17 const $ = React.unstable_useMemoCache(7);
18 - const a = t12.a;
19 - const b = t12.b;
18 + const a = t19.a;
19 + const b = t19.b;
20 const c_0 = $[0] !== a;
21 - let y;
21 + let t0;
22 if (c_0) {
23 - y = { a: a };
23 + t0 = { a: a };
24 $[0] = a;
25 - $[1] = y;
25 + $[1] = t0;
26 } else {
27 - y = $[1];
27 + t0 = $[1];
28 }
29 + const y = t0;
30 const c_2 = $[2] !== b;
30 - let z;
31 + let t1;
32 if (c_2) {
32 - z = { b: b };
33 + t1 = { b: b };
34 $[2] = b;
34 - $[3] = z;
35 + $[3] = t1;
36 } else {
36 - z = $[3];
37 + t1 = $[3];
38 }
39 + const z = t1;
40 const c_4 = $[4] !== y;
41 const c_5 = $[5] !== z;
40 - let t0;
42 + let t2;
43 if (c_4 || c_5) {
42 - t0 = { y: y, z: z };
44 + t2 = { y: y, z: z };
45 $[4] = y;
46 $[5] = z;
45 - $[6] = t0;
47 + $[6] = t2;
48 } else {
47 - t0 = $[6];
49 + t2 = $[6];
50 }
49 - return t0;
51 + return t2;
52 }
53
54 ```
compiler/forget/src/__tests__/fixtures/hir/primitive-as-dep.expect.md
+27 -22
@@ -34,54 +34,59 @@ function PrimitiveAsDep(props) {
34 const $ = React.unstable_useMemoCache(2);
35 const t0 = props.b + 1;
36 const c_0 = $[0] !== t0;
37 - let y;
37 + let t1;
38 if (c_0) {
39 - y = foo(t0);
39 + t1 = foo(t0);
40 $[0] = t0;
41 - $[1] = y;
41 + $[1] = t1;
42 } else {
43 - y = $[1];
43 + t1 = $[1];
44 }
45 + const y = t1;
46 return y;
47 }
48
49 function PrimitiveAsDepNested(props) {
49 - const $ = React.unstable_useMemoCache(8);
50 + const $ = React.unstable_useMemoCache(9);
51 const c_0 = $[0] !== props.b;
52 const c_1 = $[1] !== props.a;
53 let x;
54 + let y;
55 if (c_0 || c_1) {
56 x = {};
57 mutate(x);
58 const t0 = props.b + 1;
57 - const c_3 = $[3] !== t0;
58 - let y;
59 - if (c_3) {
60 - y = foo(t0);
61 - $[3] = t0;
62 - $[4] = y;
59 + const c_4 = $[4] !== t0;
60 + let t1;
61 + if (c_4) {
62 + t1 = foo(t0);
63 + $[4] = t0;
64 + $[5] = t1;
65 } else {
64 - y = $[4];
66 + t1 = $[5];
67 }
68 + y = t1;
69 mutate(x, props.a);
70 $[0] = props.b;
71 $[1] = props.a;
72 $[2] = x;
73 + $[3] = y;
74 } else {
75 x = $[2];
76 + y = $[3];
77 }
73 - const c_5 = $[5] !== x;
74 - const c_6 = $[6] !== y;
75 - let t1;
76 - if (c_5 || c_6) {
77 - t1 = [x, y];
78 - $[5] = x;
79 - $[6] = y;
80 - $[7] = t1;
78 + const c_6 = $[6] !== x;
79 + const c_7 = $[7] !== y;
80 + let t2;
81 + if (c_6 || c_7) {
82 + t2 = [x, y];
83 + $[6] = x;
84 + $[7] = y;
85 + $[8] = t2;
86 } else {
82 - t1 = $[7];
87 + t2 = $[8];
88 }
84 - return t1;
89 + return t2;
90 }
91
92 ```
compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md
+10 -8
@@ -19,26 +19,28 @@ function component(a, b) {
19 const $ = React.unstable_useMemoCache(5);
20 const c_0 = $[0] !== a;
21 const c_1 = $[1] !== b;
22 - let z;
22 + let t0;
23 if (c_0 || c_1) {
24 - z = { a: a, b: b };
24 + t0 = { a: a, b: b };
25 $[0] = a;
26 $[1] = b;
27 - $[2] = z;
27 + $[2] = t0;
28 } else {
29 - z = $[2];
29 + t0 = $[2];
30 }
31 + const z = t0;
32 const c_3 = $[3] !== z;
32 - let x;
33 + let t1;
34 if (c_3) {
34 - x = function () {
35 + t1 = function () {
36 z;
37 };
38 $[3] = z;
38 - $[4] = x;
39 + $[4] = t1;
40 } else {
40 - x = $[4];
41 + t1 = $[4];
42 }
43 + const x = t1;
44 return x;
45 }
46
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+10 -8
@@ -36,27 +36,29 @@ function Component(props) {
36 }
37 const y = x;
38 if (props.p1) {
39 + let t0;
40 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
40 - x = [];
41 - $[2] = x;
41 + t0 = [];
42 + $[2] = t0;
43 } else {
43 - x = $[2];
44 + t0 = $[2];
45 }
46 + x = t0;
47 }
48
49 y.push(props.p2);
50 const c_3 = $[3] !== x;
51 const c_4 = $[4] !== y;
50 - let t0;
52 + let t1;
53 if (c_3 || c_4) {
52 - t0 = <Component x={x} y={y}></Component>;
54 + t1 = <Component x={x} y={y}></Component>;
55 $[3] = x;
56 $[4] = y;
55 - $[5] = t0;
57 + $[5] = t1;
58 } else {
57 - t0 = $[5];
59 + t1 = $[5];
60 }
59 - return t0;
61 + return t1;
62 }
63
64 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+10 -9
@@ -48,14 +48,15 @@ function foo(a, b, c) {
48 x = $[1];
49 }
50 const c_2 = $[2] !== x;
51 - let y;
51 + let t0;
52 if (c_2) {
53 - y = <div>{x}</div>;
53 + t0 = <div>{x}</div>;
54 $[2] = x;
55 - $[3] = y;
55 + $[3] = t0;
56 } else {
57 - y = $[3];
57 + t0 = $[3];
58 }
59 + const y = t0;
60 bb3: switch (b) {
61 case 0: {
62 const c_4 = $[4] !== b;
@@ -83,9 +84,9 @@ function foo(a, b, c) {
84 }
85 const c_8 = $[8] !== y;
86 const c_9 = $[9] !== x;
86 - let t0;
87 + let t1;
88 if (c_8 || c_9) {
88 - t0 = (
89 + t1 = (
90 <div>
91 {y}
92 {x}
@@ -93,11 +94,11 @@ function foo(a, b, c) {
94 );
95 $[8] = y;
96 $[9] = x;
96 - $[10] = t0;
97 + $[10] = t1;
98 } else {
98 - t0 = $[10];
99 + t1 = $[10];
100 }
100 - return t0;
101 + return t1;
102 }
103
104 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md
+10 -8
@@ -30,12 +30,14 @@ function Component(props) {
30 x = [];
31 x.push(props.p0);
32 y = x;
33 + let t0;
34 if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
34 - x = [];
35 - $[4] = x;
35 + t0 = [];
36 + $[4] = t0;
37 } else {
37 - x = $[4];
38 + t0 = $[4];
39 }
40 + x = t0;
41
42 y.push(props.p1);
43 $[0] = props.p0;
@@ -48,16 +50,16 @@ function Component(props) {
50 }
51 const c_5 = $[5] !== x;
52 const c_6 = $[6] !== y;
51 - let t0;
53 + let t1;
54 if (c_5 || c_6) {
53 - t0 = <Component x={x} y={y}></Component>;
55 + t1 = <Component x={x} y={y}></Component>;
56 $[5] = x;
57 $[6] = y;
56 - $[7] = t0;
58 + $[7] = t1;
59 } else {
58 - t0 = $[7];
60 + t1 = $[7];
61 }
60 - return t0;
62 + return t1;
63 }
64
65 ```
compiler/forget/src/__tests__/fixtures/hir/reduce-reactive-deps-cond-scope.expect.md
+5 -4
@@ -60,14 +60,15 @@ function TestReactiveDepsInCondScope(props) {
60 x = {};
61 if (foo) {
62 const c_2 = $[2] !== props.a.b;
63 - let tmp;
63 + let t0;
64 if (c_2) {
65 - tmp = bar(props.a.b);
65 + t0 = bar(props.a.b);
66 $[2] = props.a.b;
67 - $[3] = tmp;
67 + $[3] = t0;
68 } else {
69 - tmp = $[3];
69 + t0 = $[3];
70 }
71 + const tmp = t0;
72 x.a = tmp;
73 }
74 $[0] = props;
compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md
+10 -9
@@ -89,9 +89,9 @@ function foo(props) {
89 }
90 const c_10 = $[10] !== x;
91 const c_11 = $[11] !== y;
92 - let content;
92 + let t1;
93 if (c_10 || c_11) {
94 - content = (
94 + t1 = (
95 <div>
96 {x}
97 {y}
@@ -99,15 +99,16 @@ function foo(props) {
99 );
100 $[10] = x;
101 $[11] = y;
102 - $[12] = content;
102 + $[12] = t1;
103 } else {
104 - content = $[12];
104 + t1 = $[12];
105 }
106 + const content = t1;
107 const c_13 = $[13] !== header;
108 const c_14 = $[14] !== content;
108 - let t1;
109 + let t2;
110 if (c_13 || c_14) {
110 - t1 = (
111 + t2 = (
112 <>
113 {header}
114 {content}
@@ -115,11 +116,11 @@ function foo(props) {
116 );
117 $[13] = header;
118 $[14] = content;
118 - $[15] = t1;
119 + $[15] = t2;
120 } else {
120 - t1 = $[15];
121 + t2 = $[15];
122 }
122 - return t1;
123 + return t2;
124 }
125
126 ```
compiler/forget/src/__tests__/fixtures/hir/same-variable-as-dep-and-redeclare.expect.md
+15 -13
@@ -58,14 +58,15 @@ function foo(props) {
58 x = $[1];
59 }
60 const c_2 = $[2] !== x;
61 - let header;
61 + let t0;
62 if (c_2) {
63 - header = <div>{x}</div>;
63 + t0 = <div>{x}</div>;
64 $[2] = x;
65 - $[3] = header;
65 + $[3] = t0;
66 } else {
67 - header = $[3];
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;
@@ -86,9 +87,9 @@ function foo(props) {
87 }
88 const c_9 = $[9] !== x;
89 const c_10 = $[10] !== y;
89 - let content;
90 + let t1;
91 if (c_9 || c_10) {
91 - content = (
92 + t1 = (
93 <div>
94 {x}
95 {y}
@@ -96,15 +97,16 @@ function foo(props) {
97 );
98 $[9] = x;
99 $[10] = y;
99 - $[11] = content;
100 + $[11] = t1;
101 } else {
101 - content = $[11];
102 + t1 = $[11];
103 }
104 + const content = t1;
105 const c_12 = $[12] !== header;
106 const c_13 = $[13] !== content;
105 - let t0;
107 + let t2;
108 if (c_12 || c_13) {
107 - t0 = (
109 + t2 = (
110 <>
111 {header}
112 {content}
@@ -112,11 +114,11 @@ function foo(props) {
114 );
115 $[12] = header;
116 $[13] = content;
115 - $[14] = t0;
117 + $[14] = t2;
118 } else {
117 - t0 = $[14];
119 + t2 = $[14];
120 }
119 - return t0;
121 + return t2;
122 }
123
124 ```
compiler/forget/src/__tests__/fixtures/hir/simple-function-1.expect.md
+5 -4
@@ -16,15 +16,16 @@ function component() {
16 ```javascript
17 function component() {
18 const $ = React.unstable_useMemoCache(1);
19 - let x;
19 + let t0;
20 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21 - x = function (a) {
21 + t0 = function (a) {
22 a.foo();
23 };
24 - $[0] = x;
24 + $[0] = t0;
25 } else {
26 - x = $[0];
26 + t0 = $[0];
27 }
28 + const x = t0;
29 return x;
30 }
31
compiler/forget/src/__tests__/fixtures/hir/simple-scope.expect.md
+5 -4
@@ -15,14 +15,15 @@ function foo(a) {
15 function foo(a) {
16 const $ = React.unstable_useMemoCache(2);
17 const c_0 = $[0] !== a.b;
18 - let x;
18 + let t0;
19 if (c_0) {
20 - x = [a.b];
20 + t0 = [a.b];
21 $[0] = a.b;
22 - $[1] = x;
22 + $[1] = t0;
23 } else {
24 - x = $[1];
24 + t0 = $[1];
25 }
26 + const x = t0;
27 return x;
28 }
29
compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md
+5 -4
@@ -16,13 +16,14 @@ function Component(props) {
16 ```javascript
17 function Component(props) {
18 const $ = React.unstable_useMemoCache(1);
19 - let x;
19 + let t0;
20 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21 - x = [1, 2];
22 - $[0] = x;
21 + t0 = [1, 2];
22 + $[0] = t0;
23 } else {
24 - x = $[0];
24 + t0 = $[0];
25 }
26 + const x = t0;
27 return x;
28 }
29
compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md
+5 -4
@@ -20,15 +20,16 @@ function Foo() {}
20
21 function Component(props) {
22 const $ = React.unstable_useMemoCache(1);
23 - let c;
23 + let t0;
24 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 const a = [];
26 const b = {};
27 - c = new Foo(a, b);
28 - $[0] = c;
27 + t0 = new Foo(a, b);
28 + $[0] = t0;
29 } else {
30 - c = $[0];
30 + t0 = $[0];
31 }
32 + const c = t0;
33 return c;
34 }
35
compiler/forget/src/__tests__/fixtures/hir/ssa-non-empty-initializer.expect.md
+5 -4
@@ -19,13 +19,14 @@ function foo(a, b) {
19 ```javascript
20 function foo(a, b) {
21 const $ = React.unstable_useMemoCache(1);
22 - let x;
22 + let t0;
23 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
24 - x = [];
25 - $[0] = x;
24 + t0 = [];
25 + $[0] = t0;
26 } else {
27 - x = $[0];
27 + t0 = $[0];
28 }
29 + let x = t0;
30 if (a) {
31 x = 1;
32 }
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+5 -4
@@ -26,13 +26,14 @@ function foo() {
26 const x = 1;
27
28 const y = 3;
29 - let t;
29 + let t0;
30 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 - t = { x: x, y: y };
32 - $[0] = t;
31 + t0 = { x: x, y: y };
32 + $[0] = t0;
33 } else {
34 - t = $[0];
34 + t0 = $[0];
35 }
36 + const t = t0;
37 return t;
38 }
39
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md
+5 -4
@@ -16,13 +16,14 @@ function Component(props) {
16 ```javascript
17 function Component(props) {
18 const $ = React.unstable_useMemoCache(1);
19 - let x;
19 + let t0;
20 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21 - x = { a: 1, b: 2 };
22 - $[0] = x;
21 + t0 = { a: 1, b: 2 };
22 + $[0] = t0;
23 } else {
24 - x = $[0];
24 + t0 = $[0];
25 }
26 + const x = t0;
27 return x;
28 }
29
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md
+10 -8
@@ -26,22 +26,24 @@ function foo(a) {
26 if (c_0) {
27 x = {};
28 if (a) {
29 - let y;
29 + let t0;
30 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
31 - y = {};
32 - $[2] = y;
31 + t0 = {};
32 + $[2] = t0;
33 } else {
34 - y = $[2];
34 + t0 = $[2];
35 }
36 + const y = t0;
37 x.y = y;
38 } else {
38 - let z;
39 + let t1;
40 if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
40 - z = {};
41 - $[3] = z;
41 + t1 = {};
42 + $[3] = t1;
43 } else {
43 - z = $[3];
44 + t1 = $[3];
45 }
46 + const z = t1;
47 x.z = z;
48 }
49 $[0] = a;
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md
+5 -4
@@ -32,13 +32,14 @@ function foo(a) {
32
33 mutate(y);
34 } else {
35 - let z;
35 + let t0;
36 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
37 - z = {};
38 - $[2] = z;
37 + t0 = {};
38 + $[2] = t0;
39 } else {
40 - z = $[2];
40 + t0 = $[2];
41 }
42 + const z = t0;
43 x.z = z;
44 }
45 $[0] = a;
compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md
+5 -4
@@ -16,13 +16,14 @@ function foo() {
16 ```javascript
17 function foo() {
18 const $ = React.unstable_useMemoCache(2);
19 - let x;
19 + let t0;
20 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21 - x = [];
22 - $[0] = x;
21 + t0 = [];
22 + $[0] = t0;
23 } else {
24 - x = $[0];
24 + t0 = $[0];
25 }
26 + const x = t0;
27 let y;
28 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29 y = {};
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+15 -12
@@ -45,12 +45,14 @@ function Component(props) {
45 }
46 case true: {
47 x.push(props.p2);
48 + let t0;
49 if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
49 - y = [];
50 - $[3] = y;
50 + t0 = [];
51 + $[3] = t0;
52 } else {
52 - y = $[3];
53 + t0 = $[3];
54 }
55 + y = t0;
56 break bb1;
57 }
58 default: {
@@ -68,27 +70,28 @@ function Component(props) {
70 y = $[2];
71 }
72 const c_4 = $[4] !== x;
71 - let child;
73 + let t1;
74 if (c_4) {
73 - child = <Component data={x}></Component>;
75 + t1 = <Component data={x}></Component>;
76 $[4] = x;
75 - $[5] = child;
77 + $[5] = t1;
78 } else {
77 - child = $[5];
79 + t1 = $[5];
80 }
81 + const child = t1;
82 y.push(props.p4);
83 const c_6 = $[6] !== y;
84 const c_7 = $[7] !== child;
82 - let t0;
85 + let t2;
86 if (c_6 || c_7) {
84 - t0 = <Component data={y}>{child}</Component>;
87 + t2 = <Component data={y}>{child}</Component>;
88 $[6] = y;
89 $[7] = child;
87 - $[8] = t0;
90 + $[8] = t2;
91 } else {
89 - t0 = $[8];
92 + t2 = $[8];
93 }
91 - return t0;
94 + return t2;
95 }
96
97 ```
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+10 -9
@@ -51,27 +51,28 @@ function Component(props) {
51 y = $[2];
52 }
53 const c_3 = $[3] !== x;
54 - let child;
54 + let t0;
55 if (c_3) {
56 - child = <Component data={x}></Component>;
56 + t0 = <Component data={x}></Component>;
57 $[3] = x;
58 - $[4] = child;
58 + $[4] = t0;
59 } else {
60 - child = $[4];
60 + t0 = $[4];
61 }
62 + const child = t0;
63 y.push(props.p4);
64 const c_5 = $[5] !== y;
65 const c_6 = $[6] !== child;
65 - let t0;
66 + let t1;
67 if (c_5 || c_6) {
67 - t0 = <Component data={y}>{child}</Component>;
68 + t1 = <Component data={y}>{child}</Component>;
69 $[5] = y;
70 $[6] = child;
70 - $[7] = t0;
71 + $[7] = t1;
72 } else {
72 - t0 = $[7];
73 + t1 = $[7];
74 }
74 - return t0;
75 + return t1;
76 }
77
78 ```
compiler/forget/src/__tests__/fixtures/hir/tagged-template-literal.expect.md
+5 -4
@@ -26,9 +26,9 @@ function component() {
26 ```javascript
27 function component() {
28 const $ = React.unstable_useMemoCache(1);
29 - let t;
29 + let t0;
30 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 - t = graphql`
31 + t0 = graphql`
32 fragment List_viewer on Viewer
33 @argumentDefinitions(
34 count: {
@@ -40,10 +40,11 @@ function component() {
40 )
41
42 `;
43 - $[0] = t;
43 + $[0] = t0;
44 } else {
45 - t = $[0];
45 + t0 = $[0];
46 }
47 + const t = t0;
48 return t;
49 }
50
compiler/forget/src/__tests__/fixtures/hir/timers.expect.md
+20 -18
@@ -20,40 +20,42 @@ function Component(props) {
20 ```javascript
21 function Component(props) {
22 const $ = React.unstable_useMemoCache(4);
23 - let start;
23 + let t0;
24 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - start = performance.now();
26 - $[0] = start;
25 + t0 = performance.now();
26 + $[0] = t0;
27 } else {
28 - start = $[0];
28 + t0 = $[0];
29 }
30 - let now;
30 + const start = t0;
31 + let t1;
32 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
32 - now = Date.now();
33 - $[1] = now;
33 + t1 = Date.now();
34 + $[1] = t1;
35 } else {
35 - now = $[1];
36 + t1 = $[1];
37 }
37 - let t0;
38 + const now = t1;
39 + let t2;
40 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
39 - t0 = performance.now();
40 - $[2] = t0;
41 + t2 = performance.now();
42 + $[2] = t2;
43 } else {
42 - t0 = $[2];
44 + t2 = $[2];
45 }
44 - const time = t0 - start;
45 - let t1;
46 + const time = t2 - start;
47 + let t3;
48 if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
47 - t1 = (
49 + t3 = (
50 <div>
51 rendering took {time} at {now}
52 </div>
53 );
52 - $[3] = t1;
54 + $[3] = t3;
55 } else {
54 - t1 = $[3];
56 + t3 = $[3];
57 }
56 - return t1;
58 + return t3;
59 }
60
61 ```
compiler/forget/src/__tests__/fixtures/hir/type-binary-operator.expect.md
+10 -8
@@ -17,20 +17,22 @@ function component() {
17 ```javascript
18 function component() {
19 const $ = React.unstable_useMemoCache(2);
20 - let a;
20 + let t0;
21 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
22 - a = some();
23 - $[0] = a;
22 + t0 = some();
23 + $[0] = t0;
24 } else {
25 - a = $[0];
25 + t0 = $[0];
26 }
27 - let b;
27 + const a = t0;
28 + let t1;
29 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29 - b = someOther();
30 - $[1] = b;
30 + t1 = someOther();
31 + $[1] = t1;
32 } else {
32 - b = $[1];
33 + t1 = $[1];
34 }
35 + const b = t1;
36 if (a > b) {
37 }
38 }
compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md
+5 -4
@@ -15,13 +15,14 @@ function component() {
15 ```javascript
16 function component() {
17 const $ = React.unstable_useMemoCache(1);
18 - let x;
18 + let t0;
19 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
20 - x = { t: 1 };
21 - $[0] = x;
20 + t0 = { t: 1 };
21 + $[0] = t0;
22 } else {
23 - x = $[0];
23 + t0 = $[0];
24 }
25 + const x = t0;
26 const p = x.t;
27 return p;
28 }
compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md
+5 -4
@@ -35,13 +35,14 @@ function component() {
35 } else {
36 t1 = $[1];
37 }
38 - let x;
38 + let t2;
39 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
40 - x = { u: t0, v: t1 };
41 - $[2] = x;
40 + t2 = { u: t0, v: t1 };
41 + $[2] = t2;
42 } else {
43 - x = $[2];
43 + t2 = $[2];
44 }
45 + const x = t2;
46 const u = x.u;
47 const v = x.v;
48 if (u > v) {
compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md
+5 -4
@@ -20,13 +20,14 @@ function component() {
20 let x;
21 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
22 x = {};
23 - let q;
23 + let t0;
24 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
25 - q = {};
26 - $[1] = q;
25 + t0 = {};
26 + $[1] = t0;
27 } else {
28 - q = $[1];
28 + t0 = $[1];
29 }
30 + const q = t0;
31 x.t = q;
32 $[0] = x;
33 } else {
compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md
+10 -8
@@ -24,20 +24,22 @@ function component() {
24 ```javascript
25 function component() {
26 const $ = React.unstable_useMemoCache(3);
27 - let p;
27 + let t0;
28 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
29 - p = makePrimitive();
30 - $[0] = p;
29 + t0 = makePrimitive();
30 + $[0] = t0;
31 } else {
32 - p = $[0];
32 + t0 = $[0];
33 }
34 - let o;
34 + const p = t0;
35 + let t1;
36 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
36 - o = {};
37 - $[1] = o;
37 + t1 = {};
38 + $[1] = t1;
39 } else {
39 - o = $[1];
40 + t1 = $[1];
41 }
42 + const o = t1;
43 let x;
44 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
45 x = {};
compiler/forget/src/__tests__/fixtures/hir/type-test-return-type-inference.expect.md
+15 -12
@@ -20,29 +20,32 @@ function component() {
20 ```javascript
21 function component() {
22 const $ = React.unstable_useMemoCache(3);
23 - let x;
23 + let t0;
24 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - x = foo();
26 - $[0] = x;
25 + t0 = foo();
26 + $[0] = t0;
27 } else {
28 - x = $[0];
28 + t0 = $[0];
29 }
30 - let y;
30 + const x = t0;
31 + let t1;
32 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
32 - y = foo();
33 - $[1] = y;
33 + t1 = foo();
34 + $[1] = t1;
35 } else {
35 - y = $[1];
36 + t1 = $[1];
37 }
38 + const y = t1;
39 if (x > y) {
40 }
39 - let z_0;
41 + let t2;
42 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
41 - z_0 = foo();
42 - $[2] = z_0;
43 + t2 = foo();
44 + $[2] = t2;
45 } else {
44 - z_0 = $[2];
46 + t2 = $[2];
47 }
48 + const z_0 = t2;
49 return z_0;
50 }
51
compiler/forget/src/__tests__/fixtures/hir/unary-expr.expect.md
+10 -9
@@ -22,14 +22,15 @@ function component(a) {
22 function component(a) {
23 const $ = React.unstable_useMemoCache(10);
24 const c_0 = $[0] !== a;
25 - let t;
25 + let t0;
26 if (c_0) {
27 - t = { t: a };
27 + t0 = { t: a };
28 $[0] = a;
29 - $[1] = t;
29 + $[1] = t0;
30 } else {
31 - t = $[1];
31 + t0 = $[1];
32 }
33 + const t = t0;
34 const z = +t.t;
35 const q = -t.t;
36 const p = void t.t;
@@ -44,9 +45,9 @@ function component(a) {
45 const c_6 = $[6] !== m;
46 const c_7 = $[7] !== e;
47 const c_8 = $[8] !== f;
47 - let t0;
48 + let t1;
49 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 + t1 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f };
51 $[2] = z;
52 $[3] = p;
53 $[4] = q;
@@ -54,11 +55,11 @@ function component(a) {
55 $[6] = m;
56 $[7] = e;
57 $[8] = f;
57 - $[9] = t0;
58 + $[9] = t1;
59 } else {
59 - t0 = $[9];
60 + t1 = $[9];
61 }
61 - return t0;
62 + return t1;
63 }
64
65 ```
compiler/forget/src/__tests__/fixtures/hir/useMemo-simple.expect.md
+10 -9
@@ -15,24 +15,25 @@ function component(a) {
15 function component(a) {
16 const $ = React.unstable_useMemoCache(4);
17 const c_0 = $[0] !== a;
18 - let x;
18 + let t0;
19 if (c_0) {
20 - x = (() => [a])();
20 + t0 = (() => [a])();
21 $[0] = a;
22 - $[1] = x;
22 + $[1] = t0;
23 } else {
24 - x = $[1];
24 + t0 = $[1];
25 }
26 + const x = t0;
27 const c_2 = $[2] !== x;
27 - let t0;
28 + let t1;
29 if (c_2) {
29 - t0 = <Foo x={x}></Foo>;
30 + t1 = <Foo x={x}></Foo>;
31 $[2] = x;
31 - $[3] = t0;
32 + $[3] = t1;
33 } else {
33 - t0 = $[3];
34 + t1 = $[3];
35 }
35 - return t0;
36 + return t1;
37 }
38
39 ```
compiler/forget/yarn.lock
+53 -18
@@ -83,13 +83,14 @@
83 "@jridgewell/gen-mapping" "^0.3.2"
84 jsesc "^2.5.1"
85
86 -"@babel/generator@^7.20.7":
87 - version "7.20.7"
88 - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a"
89 - integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==
86 +"@babel/generator@^7.21.1":
87 + version "7.21.1"
88 + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd"
89 + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==
90 dependencies:
91 - "@babel/types" "^7.20.7"
91 + "@babel/types" "^7.21.0"
92 "@jridgewell/gen-mapping" "^0.3.2"
93 + "@jridgewell/trace-mapping" "^0.3.17"
94 jsesc "^2.5.1"
95
96 "@babel/helper-annotate-as-pure@^7.18.6":
@@ -135,6 +136,14 @@
136 "@babel/template" "^7.18.10"
137 "@babel/types" "^7.19.0"
138
139 +"@babel/helper-function-name@^7.21.0":
140 + version "7.21.0"
141 + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4"
142 + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==
143 + dependencies:
144 + "@babel/template" "^7.20.7"
145 + "@babel/types" "^7.21.0"
146 +
147 "@babel/helper-hoist-variables@^7.18.6":
148 version "7.18.6"
149 resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
@@ -260,10 +269,10 @@
269 resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a"
270 integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==
271
263 -"@babel/parser@^7.20.13":
264 - version "7.20.13"
265 - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.13.tgz#ddf1eb5a813588d2fb1692b70c6fce75b945c088"
266 - integrity sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==
272 +"@babel/parser@^7.20.7", "@babel/parser@^7.21.2":
273 + version "7.21.2"
274 + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3"
275 + integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==
276
277 "@babel/plugin-syntax-async-generators@^7.8.4":
278 version "7.8.4"
@@ -459,6 +468,15 @@
468 "@babel/parser" "^7.18.10"
469 "@babel/types" "^7.18.10"
470
471 +"@babel/template@^7.20.7":
472 + version "7.20.7"
473 + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8"
474 + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==
475 + dependencies:
476 + "@babel/code-frame" "^7.18.6"
477 + "@babel/parser" "^7.20.7"
478 + "@babel/types" "^7.20.7"
479 +
480 "@babel/template@^7.3.3":
481 version "7.18.6"
482 resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31"
@@ -484,18 +502,18 @@
502 lodash "^4.17.10"
503
504 "@babel/traverse@^7.19.1":
487 - version "7.20.13"
488 - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473"
489 - integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==
505 + version "7.21.2"
506 + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75"
507 + integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==
508 dependencies:
509 "@babel/code-frame" "^7.18.6"
492 - "@babel/generator" "^7.20.7"
510 + "@babel/generator" "^7.21.1"
511 "@babel/helper-environment-visitor" "^7.18.9"
494 - "@babel/helper-function-name" "^7.19.0"
512 + "@babel/helper-function-name" "^7.21.0"
513 "@babel/helper-hoist-variables" "^7.18.6"
514 "@babel/helper-split-export-declaration" "^7.18.6"
497 - "@babel/parser" "^7.20.13"
498 - "@babel/types" "^7.20.7"
515 + "@babel/parser" "^7.21.2"
516 + "@babel/types" "^7.21.2"
517 debug "^4.1.0"
518 globals "^11.1.0"
519
@@ -543,6 +561,15 @@
561 "@babel/helper-validator-identifier" "^7.19.1"
562 to-fast-properties "^2.0.0"
563
564 +"@babel/types@^7.21.0", "@babel/types@^7.21.2":
565 + version "7.21.2"
566 + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1"
567 + integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==
568 + dependencies:
569 + "@babel/helper-string-parser" "^7.19.4"
570 + "@babel/helper-validator-identifier" "^7.19.1"
571 + to-fast-properties "^2.0.0"
572 +
573 "@bcoe/v8-coverage@^0.2.3":
574 version "0.2.3"
575 resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@@ -831,7 +858,7 @@
858 "@jridgewell/sourcemap-codec" "^1.4.10"
859 "@jridgewell/trace-mapping" "^0.3.9"
860
834 -"@jridgewell/resolve-uri@^3.0.3":
861 +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3":
862 version "3.1.0"
863 resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
864 integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
@@ -841,7 +868,7 @@
868 resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
869 integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
870
844 -"@jridgewell/sourcemap-codec@^1.4.10":
871 +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
872 version "1.4.14"
873 resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
874 integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
@@ -862,6 +889,14 @@
889 "@jridgewell/resolve-uri" "^3.0.3"
890 "@jridgewell/sourcemap-codec" "^1.4.10"
891
892 +"@jridgewell/trace-mapping@^0.3.17":
893 + version "0.3.17"
894 + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
895 + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
896 + dependencies:
897 + "@jridgewell/resolve-uri" "3.1.0"
898 + "@jridgewell/sourcemap-codec" "1.4.14"
899 +
900 "@nodelib/fs.scandir@2.1.5":
901 version "2.1.5"
902 resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"