mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Prune scopes whose values dont escape
Adds a new pass that uses escape analysis and React-specific heuristics to tune the amount of memoization applied. Specifically, the pass ensures that we only memoize: * Values which escape (are directly returned or transitively aliased by a returned value) * ...and that are not JSX elements * OR values which are _dependencies_ of scopes that produce an escaping value. The latter case is necessary to avoid breaking memoization of an escaping value bc a scope happened to have a non-escaping dependency. ## Algorithm 1. First we build up a graph, a mapping of IdentifierId to a node describing all the scopes and inputs involved in creating that identifier. Individual nodes are marked as definitely aliased, conditionally aliased, or unaliased: a. Arrays, objects, function calls all produce a new value and are always marked as aliased b. Conditional and logical expressions (and a few others) are conditinally aliased, depending on whether their result value is aliased. c. JSX is always unaliased (though its props children may be) 2. The same pass which builds the graph also stores the set of returned identifiers 3. We traverse the graph starting from the returned identifiers and mark reachable dependencies as escaping, based on the combination of the parent node's type and its children (eg a conditional node with an aliased dep promotes to aliased). 4. Finally we prune scopes whose outputs weren't marked.
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
mergeOverlappingReactiveScopes,
|
||||
promoteUsedTemporaries,
|
||||
propagateScopeDependencies,
|
||||
pruneNonEscapingScopes,
|
||||
pruneNonReactiveDependencies,
|
||||
pruneUnusedLabels,
|
||||
pruneUnusedLValues,
|
||||
@@ -145,6 +146,13 @@ export function* run(
|
||||
value: reactiveFunction,
|
||||
});
|
||||
|
||||
pruneNonEscapingScopes(reactiveFunction);
|
||||
yield log({
|
||||
kind: "reactive",
|
||||
name: "PruneNonEscapingDependencies",
|
||||
value: reactiveFunction,
|
||||
});
|
||||
|
||||
pruneNonReactiveDependencies(reactiveFunction);
|
||||
yield log({
|
||||
kind: "reactive",
|
||||
|
||||
@@ -84,9 +84,7 @@ function printReactiveInstruction(
|
||||
const id = `[${instruction.id}]`;
|
||||
|
||||
if (instruction.lvalue !== null) {
|
||||
writer.write(
|
||||
`${id} ${printIdentifier(instruction.lvalue.identifier)} = `
|
||||
);
|
||||
writer.write(`${id} ${printPlace(instruction.lvalue)} = `);
|
||||
printReactiveValue(writer, instruction.value);
|
||||
writer.newline();
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,581 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import prettyFormat from "pretty-format";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
Effect,
|
||||
IdentifierId,
|
||||
InstructionId,
|
||||
Place,
|
||||
ReactiveFunction,
|
||||
ReactiveInstruction,
|
||||
ReactiveScopeBlock,
|
||||
ReactiveStatement,
|
||||
ReactiveTerminal,
|
||||
ReactiveTerminalStatement,
|
||||
ReactiveValue,
|
||||
ScopeId,
|
||||
} from "../HIR";
|
||||
import { eachInstructionLValue } from "../HIR/visitors";
|
||||
import { log } from "../Utils/logger";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import { getPlaceScope } from "./BuildReactiveBlocks";
|
||||
import { printReactiveFunction } from "./PrintReactiveFunction";
|
||||
import {
|
||||
eachReactiveValueOperand,
|
||||
ReactiveFunctionTransform,
|
||||
ReactiveFunctionVisitor,
|
||||
Transformed,
|
||||
visitReactiveFunction,
|
||||
} from "./visitors";
|
||||
|
||||
/**
|
||||
* This pass prunes reactive scopes that are not necessary to bound downstream computation.
|
||||
* Specifically, the pass identifies the set of identifiers which are directly returned by
|
||||
* the function and/or transitively aliased by a return value - ie, values that "escape".
|
||||
*
|
||||
* Example to build intuition:
|
||||
*
|
||||
* ```javascript
|
||||
* function Component(props) {
|
||||
* const a = {}; // not aliased or returned: *not* memoized
|
||||
* const b = {}; // aliased by c, which is returned: memoized
|
||||
* const c = [b]; // directly returned: memoized
|
||||
* return c;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* However, this logic alone is insufficient for two reasons:
|
||||
* - Statically memoizing JSX elements *may* be inefficient compared to using dynamic
|
||||
* memoization with `React.memo()`. Static memoization may be JIT'd and can look at
|
||||
* the precise props w/o dynamic iteration, but incurs potentially large code-size
|
||||
* overhead. Dynamic memoization with `React.memo()` incurs potentially increased
|
||||
* runtime overhead for smaller code size. We plan to experiment with both variants
|
||||
* for JSX.
|
||||
* - Because we merge values whose mutations _interleave_ into a single scope, there
|
||||
* can be cases where a non-escaping value needs to be memoized anyway to avoid breaking
|
||||
* a memoization input. As a rule, for any scope that has a memoized output, all of that
|
||||
* scope's transitive dependencies must also be memoized _even if they don't escape_.
|
||||
* Failing to memoize them would cause the scope to invalidate more often than necessary
|
||||
* and break downstream memoization.
|
||||
*
|
||||
* Example of this second case:
|
||||
*
|
||||
* ```javascript
|
||||
* function Component(props) {
|
||||
* // a can be independently memoized but it doesn't escape, so naively we may think its
|
||||
* // safe to not memoize. but not memoizing would break caching of b, which does
|
||||
* // escape.
|
||||
* const a = [props.a];
|
||||
*
|
||||
* // b and c are interleaved and grouped into a single scope,
|
||||
* // but they are independent values. c does not escape, but
|
||||
* // we need to ensure that a is memoized or else b will invalidate
|
||||
* // on every render since a is a dependency.
|
||||
* const b = [];
|
||||
* const c = {};
|
||||
* c.a = a;
|
||||
* b.push(props.b);
|
||||
*
|
||||
* return b;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ## Algorithm
|
||||
*
|
||||
* 1. First we build up a graph, a mapping of IdentifierId to a node describing all the
|
||||
* scopes and inputs involved in creating that identifier. Individual nodes are marked
|
||||
* as definitely aliased, conditionally aliased, or unaliased:
|
||||
* a. Arrays, objects, function calls all produce a new value and are always marked as aliased
|
||||
* b. Conditional and logical expressions (and a few others) are conditinally aliased,
|
||||
* depending on whether their result value is aliased.
|
||||
* c. JSX is always unaliased (though its props children may be)
|
||||
* 2. The same pass which builds the graph also stores the set of returned identifiers.
|
||||
* 3. We traverse the graph starting from the returned identifiers and mark reachable dependencies
|
||||
* as escaping, based on the combination of the parent node's type and its children (eg a
|
||||
* conditional node with an aliased dep promotes to aliased).
|
||||
* 4. Finally we prune scopes whose outputs weren't marked.
|
||||
*/
|
||||
export function pruneNonEscapingScopes(fn: ReactiveFunction): void {
|
||||
// First build up a map of which instructions are involved in creating which values,
|
||||
// and which values are returned.
|
||||
const state = new State();
|
||||
if (fn.id !== null) {
|
||||
state.declare(fn.id.id);
|
||||
}
|
||||
for (const param of fn.params) {
|
||||
state.declare(param.identifier.id);
|
||||
}
|
||||
visitReactiveFunction(fn, new CollectDependenciesVisitor(), state);
|
||||
|
||||
log(() => prettyFormat(state));
|
||||
|
||||
// Then walk outward from the returned values and find all captured operands.
|
||||
// This forms the set of identifiers which should be memoized.
|
||||
const memoized = computeMemoizedIdentifiers(state);
|
||||
|
||||
log(() => prettyFormat(memoized));
|
||||
|
||||
log(() => printReactiveFunction(fn));
|
||||
|
||||
// Prune scopes that do not declare/reassign any escaping values
|
||||
visitReactiveFunction(fn, new PruneScopesTransform(), memoized);
|
||||
}
|
||||
|
||||
// Describes how to determine whether a value should be memoized, relative to dependees and dependencies
|
||||
enum MemoizationLevel {
|
||||
// The value should be memoized if it escapes
|
||||
Memoized = "Memoized",
|
||||
// Values that are memoized if their dependencies are memoized (used for logical/ternary and
|
||||
// other expressions that propagate dependencies wo changing them)
|
||||
Conditional = "Conditional",
|
||||
// Values that cannot be compared with Object.is, but which by default don't need to be memoized
|
||||
// unless forced
|
||||
Unmemoized = "Unmemoized",
|
||||
// The value will never be memoized: used for values that can be cheaply compared w Object.is
|
||||
Never = "Never",
|
||||
}
|
||||
|
||||
// Given an identifier that appears as an lvalue multiple times with different memoization levels,
|
||||
// determines the final memoization level.
|
||||
function joinAliases(
|
||||
kind1: MemoizationLevel,
|
||||
kind2: MemoizationLevel
|
||||
): MemoizationLevel {
|
||||
if (
|
||||
kind1 === MemoizationLevel.Memoized ||
|
||||
kind2 === MemoizationLevel.Memoized
|
||||
) {
|
||||
return MemoizationLevel.Memoized;
|
||||
} else if (
|
||||
kind1 === MemoizationLevel.Conditional ||
|
||||
kind2 === MemoizationLevel.Conditional
|
||||
) {
|
||||
return MemoizationLevel.Conditional;
|
||||
} else if (
|
||||
kind1 === MemoizationLevel.Unmemoized ||
|
||||
kind2 === MemoizationLevel.Unmemoized
|
||||
) {
|
||||
return MemoizationLevel.Unmemoized;
|
||||
} else {
|
||||
return MemoizationLevel.Never;
|
||||
}
|
||||
}
|
||||
|
||||
// A node in the graph describing the memoization level of a given identifier as well as its dependencies and scopes.
|
||||
type IdentifierNode = {
|
||||
level: MemoizationLevel;
|
||||
memoized: boolean;
|
||||
dependencies: Set<IdentifierId>;
|
||||
scopes: Set<ScopeId>;
|
||||
seen: boolean;
|
||||
};
|
||||
|
||||
// A scope node describing its dependencies
|
||||
type ScopeNode = {
|
||||
dependencies: Array<IdentifierId>;
|
||||
seen: boolean;
|
||||
};
|
||||
|
||||
// Stores the identifier and scope graphs, set of returned identifiers, etc
|
||||
class State {
|
||||
// Maps lvalues for LoadLocal to the identifier being loaded, to resolve indirections
|
||||
// in subsequent lvalues/rvalues
|
||||
definitions: Map<IdentifierId, IdentifierId> = new Map();
|
||||
|
||||
identifiers: Map<IdentifierId, IdentifierNode> = new Map();
|
||||
scopes: Map<ScopeId, ScopeNode> = new Map();
|
||||
returned: Set<IdentifierId> = new Set();
|
||||
|
||||
/**
|
||||
* Declare a new identifier, used for function id and params
|
||||
*/
|
||||
declare(id: IdentifierId): void {
|
||||
this.identifiers.set(id, {
|
||||
level: MemoizationLevel.Never,
|
||||
memoized: false,
|
||||
dependencies: new Set(),
|
||||
scopes: new Set(),
|
||||
seen: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the identifier with its scope, if there is one and it is active for the given instruction id:
|
||||
* - Records the scope and its dependencies
|
||||
* - Associates the identifier with this scope
|
||||
*/
|
||||
visitOperand(
|
||||
id: InstructionId,
|
||||
place: Place,
|
||||
identifier: IdentifierId
|
||||
): void {
|
||||
const scope = getPlaceScope(id, place);
|
||||
if (scope !== null) {
|
||||
let node = this.scopes.get(scope.id);
|
||||
if (node === undefined) {
|
||||
node = {
|
||||
dependencies: [...scope.dependencies].map((dep) => dep.identifier.id),
|
||||
seen: false,
|
||||
};
|
||||
this.scopes.set(scope.id, node);
|
||||
}
|
||||
const identifierNode = this.identifiers.get(identifier);
|
||||
invariant(
|
||||
identifierNode !== undefined,
|
||||
"Expected identifier to be initialized"
|
||||
);
|
||||
identifierNode.scopes.add(scope.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a state derived from visiting the function, walks the graph from the returned nodes
|
||||
* to determine which other values should be memoized. Returns a set of all identifiers
|
||||
* that should be memoized.
|
||||
*/
|
||||
function computeMemoizedIdentifiers(state: State): Set<IdentifierId> {
|
||||
const memoized = new Set<IdentifierId>();
|
||||
|
||||
// Visit an identifier, optionally forcing it to be memoized
|
||||
function visit(id: IdentifierId, forceMemoize: boolean = false): boolean {
|
||||
const node = state.identifiers.get(id);
|
||||
invariant(node !== undefined, "Expected a node for all identifiers");
|
||||
if (node.seen) {
|
||||
return node.memoized;
|
||||
}
|
||||
node.seen = true;
|
||||
|
||||
// Note: in case of cycles we temporarily mark the identifier as non-memoized,
|
||||
// this is reset later after processing dependencies
|
||||
node.memoized = false;
|
||||
|
||||
// Visit dependencies, determine if any of them are memoized
|
||||
let hasMemoizedDependency = false;
|
||||
for (const dep of node.dependencies) {
|
||||
const isDepMemoized = visit(dep);
|
||||
hasMemoizedDependency ||= isDepMemoized;
|
||||
}
|
||||
|
||||
if (
|
||||
node.level === MemoizationLevel.Memoized ||
|
||||
(node.level === MemoizationLevel.Conditional &&
|
||||
(hasMemoizedDependency || forceMemoize)) ||
|
||||
(node.level === MemoizationLevel.Unmemoized && forceMemoize)
|
||||
) {
|
||||
node.memoized = true;
|
||||
memoized.add(id);
|
||||
for (const scope of node.scopes) {
|
||||
forceMemoizeScopeDependencies(scope);
|
||||
}
|
||||
}
|
||||
return node.memoized;
|
||||
}
|
||||
|
||||
// Force all the scope's optionally-memoizeable dependencies (not "Never") to be memoized
|
||||
function forceMemoizeScopeDependencies(id: ScopeId): void {
|
||||
const node = state.scopes.get(id);
|
||||
invariant(node !== undefined, "Expected a node for all scopes");
|
||||
if (node.seen) {
|
||||
return;
|
||||
}
|
||||
node.seen = true;
|
||||
|
||||
for (const dep of node.dependencies) {
|
||||
visit(dep, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk from the "roots" aka returned identifiers.
|
||||
for (const returned of state.returned) {
|
||||
visit(returned);
|
||||
}
|
||||
|
||||
return memoized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a value, returns a description of how it should be memoized:
|
||||
* - lvalues: optional extra places that are lvalue-like in the sense of
|
||||
* aliasing the rvalues
|
||||
* - rvalues: places that are aliased by the instruction's lvalues.
|
||||
* - level: the level of memoization to apply to this value
|
||||
*/
|
||||
function computeMemoizationInputs(value: ReactiveValue): {
|
||||
// can optionally return a custom set of lvalues per instruction
|
||||
lvalues: Array<Place> | null;
|
||||
rvalues: Array<Place>;
|
||||
level: MemoizationLevel;
|
||||
} {
|
||||
switch (value.kind) {
|
||||
case "ConditionalExpression": {
|
||||
return {
|
||||
lvalues: null,
|
||||
rvalues: [
|
||||
// Conditionals do not alias their test value.
|
||||
...computeMemoizationInputs(value.consequent).rvalues,
|
||||
...computeMemoizationInputs(value.alternate).rvalues,
|
||||
],
|
||||
// Only need to memoize if the rvalues are memoized
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "LogicalExpression": {
|
||||
return {
|
||||
lvalues: null,
|
||||
rvalues: [
|
||||
...computeMemoizationInputs(value.left).rvalues,
|
||||
...computeMemoizationInputs(value.right).rvalues,
|
||||
],
|
||||
// Only need to memoize if the rvalues are memoized
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "SequenceExpression": {
|
||||
return {
|
||||
lvalues: null,
|
||||
// Only the final value of the sequence is a true rvalue:
|
||||
// values from the sequence's instructions are evaluated
|
||||
// as separate nodes
|
||||
rvalues: computeMemoizationInputs(value.value).rvalues,
|
||||
// Only memoize if the final value was memoized
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "JsxExpression": {
|
||||
const operands: Array<Place> = [];
|
||||
operands.push(value.tag);
|
||||
for (const prop of value.props) {
|
||||
if (prop.kind === "JsxAttribute") {
|
||||
operands.push(prop.place);
|
||||
} else {
|
||||
operands.push(prop.argument);
|
||||
}
|
||||
}
|
||||
if (value.children !== null) {
|
||||
for (const child of value.children) {
|
||||
operands.push(child);
|
||||
}
|
||||
}
|
||||
return {
|
||||
lvalues: null,
|
||||
rvalues: operands,
|
||||
// JSX elements themselves are not memoized unless forced to
|
||||
// avoid breaking downstream memoization
|
||||
level: MemoizationLevel.Unmemoized,
|
||||
};
|
||||
}
|
||||
case "JsxFragment": {
|
||||
return {
|
||||
lvalues: null,
|
||||
rvalues: value.children,
|
||||
// JSX elements themselves are not memoized unless forced to
|
||||
// avoid breaking downstream memoization
|
||||
level: MemoizationLevel.Unmemoized,
|
||||
};
|
||||
}
|
||||
case "ComputedDelete":
|
||||
case "PropertyDelete":
|
||||
case "LoadGlobal":
|
||||
case "TemplateLiteral":
|
||||
case "Primitive":
|
||||
case "JSXText":
|
||||
case "BinaryExpression":
|
||||
case "UnaryExpression": {
|
||||
return {
|
||||
lvalues: null,
|
||||
rvalues: [],
|
||||
// All of these instructions return a primitive value and never need to be memoized
|
||||
level: MemoizationLevel.Never,
|
||||
};
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
return {
|
||||
lvalues: null,
|
||||
// Indirection for the inner value, memoized if the value is
|
||||
rvalues: [value.value],
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "LoadLocal": {
|
||||
return {
|
||||
lvalues: null,
|
||||
// Indirection for the inner value, memoized if the value is
|
||||
rvalues: [value.place],
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "Destructure":
|
||||
case "StoreLocal": {
|
||||
return {
|
||||
lvalues: null,
|
||||
// Indirection for the inner value, memoized if the value is
|
||||
rvalues: [value.value],
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "ComputedLoad":
|
||||
case "PropertyLoad": {
|
||||
return {
|
||||
lvalues: null,
|
||||
// Only the object is aliased to the result, and the result only needs to be
|
||||
// memoized if the object is
|
||||
rvalues: [value.object],
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "ComputedStore": {
|
||||
// The object being stored to acts as an lvalue (it aliases the value), but
|
||||
// the computed key is not aliased
|
||||
return {
|
||||
lvalues: [value.object],
|
||||
rvalues: [value.value],
|
||||
level: MemoizationLevel.Conditional,
|
||||
};
|
||||
}
|
||||
case "FunctionExpression":
|
||||
case "TaggedTemplateExpression":
|
||||
case "CallExpression":
|
||||
case "ArrayExpression":
|
||||
case "NewExpression":
|
||||
case "ObjectExpression":
|
||||
case "ComputedCall":
|
||||
case "PropertyCall":
|
||||
case "PropertyStore": {
|
||||
// All of these instructions may produce new values which must be memoized if
|
||||
// reachable from a return value. Any mutable rvalue may alias any other rvalue
|
||||
const operands = [...eachReactiveValueOperand(value)];
|
||||
return {
|
||||
lvalues: operands.filter((operand) => isMutableEffect(operand.effect)),
|
||||
rvalues: operands,
|
||||
level: MemoizationLevel.Memoized,
|
||||
};
|
||||
}
|
||||
case "UnsupportedNode": {
|
||||
CompilerError.invariant(`Unexpected unsupported node`, value.loc);
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(value, `Unexpected value kind '${(value as any).kind}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the input state with the set of returned identifiers and information about each
|
||||
* identifier's and scope's dependencies.
|
||||
*/
|
||||
class CollectDependenciesVisitor extends ReactiveFunctionVisitor<State> {
|
||||
override visitInstruction(
|
||||
instruction: ReactiveInstruction,
|
||||
state: State
|
||||
): void {
|
||||
this.traverseInstruction(instruction, state);
|
||||
|
||||
// Determe the level of memoization for this value and the lvalues/rvalues
|
||||
const aliasing = computeMemoizationInputs(instruction.value);
|
||||
|
||||
// Associate all the rvalues with the instruction's scope if it has one
|
||||
for (const operand of aliasing.rvalues) {
|
||||
const operandId =
|
||||
state.definitions.get(operand.identifier.id) ?? operand.identifier.id;
|
||||
state.visitOperand(instruction.id, operand, operandId);
|
||||
}
|
||||
|
||||
// Add the operands as dependencies of all lvalues.
|
||||
const lvalues =
|
||||
aliasing.lvalues !== null
|
||||
? [...eachInstructionLValue(instruction), ...aliasing.lvalues]
|
||||
: [...eachInstructionLValue(instruction)];
|
||||
for (const lvalue of lvalues) {
|
||||
const lvalueId =
|
||||
state.definitions.get(lvalue.identifier.id) ?? lvalue.identifier.id;
|
||||
let node = state.identifiers.get(lvalueId);
|
||||
if (node === undefined) {
|
||||
node = {
|
||||
level: MemoizationLevel.Never,
|
||||
memoized: false,
|
||||
dependencies: new Set(),
|
||||
scopes: new Set(),
|
||||
seen: false,
|
||||
};
|
||||
state.identifiers.set(lvalueId, node);
|
||||
}
|
||||
node.level = joinAliases(node.level, aliasing.level);
|
||||
// This looks like NxM iterations but in practice all instructions with multiple
|
||||
// lvalues have only a single rvalue
|
||||
for (const operand of aliasing.rvalues) {
|
||||
const operandId =
|
||||
state.definitions.get(operand.identifier.id) ?? operand.identifier.id;
|
||||
if (operandId === lvalueId) {
|
||||
continue;
|
||||
}
|
||||
node.dependencies.add(operandId);
|
||||
}
|
||||
|
||||
state.visitOperand(instruction.id, lvalue, lvalueId);
|
||||
}
|
||||
|
||||
if (instruction.value.kind === "LoadLocal" && instruction.lvalue !== null) {
|
||||
state.definitions.set(
|
||||
instruction.lvalue.identifier.id,
|
||||
instruction.value.place.identifier.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
override visitTerminal(
|
||||
stmt: ReactiveTerminalStatement<ReactiveTerminal>,
|
||||
state: State
|
||||
): void {
|
||||
this.traverseTerminal(stmt, state);
|
||||
|
||||
if (stmt.terminal.kind === "return" && stmt.terminal.value !== null) {
|
||||
state.returned.add(stmt.terminal.value.identifier.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune reactive scopes that do not have any memoized outputs
|
||||
*/
|
||||
class PruneScopesTransform extends ReactiveFunctionTransform<
|
||||
Set<IdentifierId>
|
||||
> {
|
||||
override transformScope(
|
||||
scope: ReactiveScopeBlock,
|
||||
state: Set<IdentifierId>
|
||||
): Transformed<ReactiveStatement> {
|
||||
this.visitScope(scope, state);
|
||||
const hasMemoizedOutput =
|
||||
Array.from(scope.scope.declarations.keys()).some((id) => state.has(id)) ||
|
||||
Array.from(scope.scope.reassignments).some((identifier) =>
|
||||
state.has(identifier.id)
|
||||
);
|
||||
if (hasMemoizedOutput) {
|
||||
return { kind: "keep" };
|
||||
} else {
|
||||
return { kind: "replace-many", value: scope.instructions };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isMutableEffect(effect: Effect): boolean {
|
||||
switch (effect) {
|
||||
case Effect.Capture:
|
||||
case Effect.Mutate:
|
||||
case Effect.Store: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export { mergeOverlappingReactiveScopes } from "./MergeOverlappingReactiveScopes
|
||||
export { printReactiveFunction } from "./PrintReactiveFunction";
|
||||
export { promoteUsedTemporaries } from "./PromoteUsedTemporaries";
|
||||
export { propagateScopeDependencies } from "./PropagateScopeDependencies";
|
||||
export { pruneNonEscapingScopes } from "./PruneNonEscapingScopes";
|
||||
export { pruneNonReactiveDependencies } from "./PruneNonReactiveDependencies";
|
||||
export { pruneTemporaryLValues as pruneUnusedLValues } from "./PruneTemporaryLValues";
|
||||
export { pruneUnusedLabels } from "./PruneUnusedLabels";
|
||||
|
||||
+3
-11
@@ -19,7 +19,7 @@ function component(a, b) {
|
||||
|
||||
```javascript
|
||||
function component(a, b) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== a;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
@@ -30,16 +30,8 @@ function component(a, b) {
|
||||
t0 = $[1];
|
||||
}
|
||||
const z = t0;
|
||||
const c_2 = $[2] !== b;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = { b };
|
||||
$[2] = b;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const z_0 = t1;
|
||||
|
||||
const z_0 = { b };
|
||||
(function () {
|
||||
mutate(z);
|
||||
})();
|
||||
|
||||
+19
-28
@@ -24,7 +24,7 @@ function AllocatingPrimitiveAsDepNested(props) {
|
||||
// Correctness:
|
||||
// - y depends on either bar(props.b) or bar(props.b) + 1
|
||||
function AllocatingPrimitiveAsDepNested(props) {
|
||||
const $ = React.unstable_useMemoCache(11);
|
||||
const $ = React.unstable_useMemoCache(9);
|
||||
const c_0 = $[0] !== props.b;
|
||||
const c_1 = $[1] !== props.a;
|
||||
let x;
|
||||
@@ -32,26 +32,17 @@ function AllocatingPrimitiveAsDepNested(props) {
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
mutate(x);
|
||||
const c_4 = $[4] !== props.b;
|
||||
let t0;
|
||||
const t0 = bar(props.b) + 1;
|
||||
const c_4 = $[4] !== t0;
|
||||
let t1;
|
||||
if (c_4) {
|
||||
t0 = bar(props.b);
|
||||
$[4] = props.b;
|
||||
$[5] = t0;
|
||||
t1 = foo(t0);
|
||||
$[4] = t0;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
t1 = $[5];
|
||||
}
|
||||
const t1 = t0 + 1;
|
||||
const c_6 = $[6] !== t1;
|
||||
let t2;
|
||||
if (c_6) {
|
||||
t2 = foo(t1);
|
||||
$[6] = t1;
|
||||
$[7] = t2;
|
||||
} else {
|
||||
t2 = $[7];
|
||||
}
|
||||
y = t2;
|
||||
y = t1;
|
||||
mutate(x, props.a);
|
||||
$[0] = props.b;
|
||||
$[1] = props.a;
|
||||
@@ -61,18 +52,18 @@ function AllocatingPrimitiveAsDepNested(props) {
|
||||
x = $[2];
|
||||
y = $[3];
|
||||
}
|
||||
const c_8 = $[8] !== x;
|
||||
const c_9 = $[9] !== y;
|
||||
let t3;
|
||||
if (c_8 || c_9) {
|
||||
t3 = [x, y];
|
||||
$[8] = x;
|
||||
$[9] = y;
|
||||
$[10] = t3;
|
||||
const c_6 = $[6] !== x;
|
||||
const c_7 = $[7] !== y;
|
||||
let t2;
|
||||
if (c_6 || c_7) {
|
||||
t2 = [x, y];
|
||||
$[6] = x;
|
||||
$[7] = y;
|
||||
$[8] = t2;
|
||||
} else {
|
||||
t3 = $[10];
|
||||
t2 = $[8];
|
||||
}
|
||||
return t3;
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -21,27 +21,18 @@ function AllocatingPrimitiveAsDep(props) {
|
||||
// Correctness:
|
||||
// - y depends on either bar(props.b) or bar(props.b) + 1
|
||||
function AllocatingPrimitiveAsDep(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const t0 = bar(props).b + 1;
|
||||
const c_0 = $[0] !== t0;
|
||||
let t1;
|
||||
if (c_0) {
|
||||
t0 = bar(props);
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
t1 = foo(t0);
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
t1 = $[1];
|
||||
}
|
||||
const t1 = t0.b + 1;
|
||||
const c_2 = $[2] !== t1;
|
||||
let t2;
|
||||
if (c_2) {
|
||||
t2 = foo(t1);
|
||||
$[2] = t1;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
const y = t2;
|
||||
const y = t1;
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ function Component(props) {
|
||||
function foo() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let a;
|
||||
let b;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
@@ -36,14 +36,7 @@ function Component(props) {
|
||||
a = $[0];
|
||||
b = $[1];
|
||||
}
|
||||
let t0;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <div a={a} b={b}></div>;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
return <div a={a} b={b}></div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ function component(a, b) {
|
||||
|
||||
```javascript
|
||||
function component(a, b) {
|
||||
const $ = React.unstable_useMemoCache(9);
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== b;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
@@ -56,16 +56,7 @@ function component(a, b) {
|
||||
t2 = $[6];
|
||||
}
|
||||
const x = t2;
|
||||
const c_7 = $[7] !== x;
|
||||
let t3;
|
||||
if (c_7) {
|
||||
t3 = <Foo x={x}></Foo>;
|
||||
$[7] = x;
|
||||
$[8] = t3;
|
||||
} else {
|
||||
t3 = $[8];
|
||||
}
|
||||
const t = t3;
|
||||
const t = <Foo x={x}></Foo>;
|
||||
mutate(x);
|
||||
return t;
|
||||
}
|
||||
|
||||
+2
-13
@@ -20,7 +20,7 @@ function component({ mutator }) {
|
||||
|
||||
```javascript
|
||||
function component(t27) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const { mutator } = t27;
|
||||
const c_0 = $[0] !== mutator;
|
||||
let t0;
|
||||
@@ -46,18 +46,7 @@ function component(t27) {
|
||||
t1 = $[3];
|
||||
}
|
||||
const hide = t1;
|
||||
const c_4 = $[4] !== poke;
|
||||
const c_5 = $[5] !== hide;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = <Foo poke={poke} hide={hide}></Foo>;
|
||||
$[4] = poke;
|
||||
$[5] = hide;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
return <Foo poke={poke} hide={hide}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(10);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const items = props.items;
|
||||
const maxItems = props.maxItems;
|
||||
const c_0 = $[0] !== maxItems;
|
||||
@@ -44,16 +44,7 @@ function Component(props) {
|
||||
if (c_0 || c_1) {
|
||||
renderedItems = [];
|
||||
const seen = new Set();
|
||||
const c_3 = $[3] !== maxItems;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = Math.max(0, maxItems);
|
||||
$[3] = maxItems;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
const max = t0;
|
||||
const max = Math.max(0, maxItems);
|
||||
for (let i = 0; i < items.length; i = i + 1, i) {
|
||||
const item = items.at(i);
|
||||
if (item == null || seen.has(item)) {
|
||||
@@ -74,32 +65,12 @@ function Component(props) {
|
||||
}
|
||||
|
||||
const count = renderedItems.length;
|
||||
const c_5 = $[5] !== count;
|
||||
let t1;
|
||||
if (c_5) {
|
||||
t1 = <h1>{count} Items</h1>;
|
||||
$[5] = count;
|
||||
$[6] = t1;
|
||||
} else {
|
||||
t1 = $[6];
|
||||
}
|
||||
const c_7 = $[7] !== t1;
|
||||
const c_8 = $[8] !== renderedItems;
|
||||
let t2;
|
||||
if (c_7 || c_8) {
|
||||
t2 = (
|
||||
<div>
|
||||
{t1}
|
||||
{renderedItems}
|
||||
</div>
|
||||
);
|
||||
$[7] = t1;
|
||||
$[8] = renderedItems;
|
||||
$[9] = t2;
|
||||
} else {
|
||||
t2 = $[9];
|
||||
}
|
||||
return t2;
|
||||
return (
|
||||
<div>
|
||||
{<h1>{count} Items</h1>}
|
||||
{renderedItems}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -14,7 +14,7 @@ function component() {
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const [x, setX] = useState(0);
|
||||
const c_0 = $[0] !== setX;
|
||||
let t0;
|
||||
@@ -26,16 +26,7 @@ function component() {
|
||||
t0 = $[1];
|
||||
}
|
||||
const handler = t0;
|
||||
const c_2 = $[2] !== handler;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = <Foo handler={handler}></Foo>;
|
||||
$[2] = handler;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
return <Foo handler={handler}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ function mayMutate() {}
|
||||
|
||||
```javascript
|
||||
function ComponentA(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props;
|
||||
let a;
|
||||
let b;
|
||||
@@ -55,22 +55,11 @@ function ComponentA(props) {
|
||||
a = $[1];
|
||||
b = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== a;
|
||||
const c_4 = $[4] !== b;
|
||||
let t0;
|
||||
if (c_3 || c_4) {
|
||||
t0 = <Foo a={a} b={b}></Foo>;
|
||||
$[3] = a;
|
||||
$[4] = b;
|
||||
$[5] = t0;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
}
|
||||
return t0;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
function ComponentB(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props;
|
||||
let a;
|
||||
let b;
|
||||
@@ -90,18 +79,7 @@ function ComponentB(props) {
|
||||
a = $[1];
|
||||
b = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== a;
|
||||
const c_4 = $[4] !== b;
|
||||
let t0;
|
||||
if (c_3 || c_4) {
|
||||
t0 = <Foo a={a} b={b}></Foo>;
|
||||
$[3] = a;
|
||||
$[4] = b;
|
||||
$[5] = t0;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
}
|
||||
return t0;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
function Foo() {}
|
||||
|
||||
@@ -16,16 +16,9 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let y;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = 0;
|
||||
for (const x = 100; false; 100) {
|
||||
y = y + 1;
|
||||
}
|
||||
$[0] = y;
|
||||
} else {
|
||||
y = $[0];
|
||||
let y = 0;
|
||||
for (const x = 100; false; 100) {
|
||||
y = y + 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@@ -17,16 +17,9 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let y;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = 0;
|
||||
while (false) {
|
||||
y = y + 1;
|
||||
}
|
||||
$[0] = y;
|
||||
} else {
|
||||
y = $[0];
|
||||
let y = 0;
|
||||
while (false) {
|
||||
y = y + 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ function Component(props) {
|
||||
function Foo() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let a;
|
||||
let b;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
@@ -35,14 +35,7 @@ function Component(props) {
|
||||
a = $[0];
|
||||
b = $[1];
|
||||
}
|
||||
let t0;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <div a={a} b={b}></div>;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
return <div a={a} b={b}></div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -14,7 +14,7 @@ function component() {
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const [x, setX] = useState(0);
|
||||
const c_0 = $[0] !== setX;
|
||||
let t0;
|
||||
@@ -26,18 +26,7 @@ function component() {
|
||||
t0 = $[1];
|
||||
}
|
||||
const handler = t0;
|
||||
const c_2 = $[2] !== handler;
|
||||
const c_3 = $[3] !== x;
|
||||
let t1;
|
||||
if (c_2 || c_3) {
|
||||
t1 = <input onChange={handler} value={x}></input>;
|
||||
$[2] = handler;
|
||||
$[3] = x;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
return t1;
|
||||
return <input onChange={handler} value={x}></input>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -18,18 +18,9 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.max;
|
||||
let y;
|
||||
if (c_0) {
|
||||
y = 0;
|
||||
while (y < props.max) {
|
||||
y = y + 1;
|
||||
}
|
||||
$[0] = props.max;
|
||||
$[1] = y;
|
||||
} else {
|
||||
y = $[1];
|
||||
let y = 0;
|
||||
while (y < props.max) {
|
||||
y = y + 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
+2
-16
@@ -16,22 +16,8 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== props.b;
|
||||
let x;
|
||||
let y;
|
||||
if (c_0 || c_1) {
|
||||
({ x, y } = { x: props.a, y: props.b });
|
||||
console.log(x);
|
||||
$[0] = props.a;
|
||||
$[1] = props.b;
|
||||
$[2] = x;
|
||||
$[3] = y;
|
||||
} else {
|
||||
x = $[2];
|
||||
y = $[3];
|
||||
}
|
||||
let { x, y } = { x: props.a, y: props.b };
|
||||
console.log(x);
|
||||
x = props.c;
|
||||
return x + y;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const x = [];
|
||||
if (a) {
|
||||
const y = [];
|
||||
if (b) {
|
||||
y.push(c);
|
||||
}
|
||||
x.push(<div>{y}</div>);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== a;
|
||||
const c_1 = $[1] !== b;
|
||||
const c_2 = $[2] !== c;
|
||||
let x;
|
||||
if (c_0 || c_1 || c_2) {
|
||||
x = [];
|
||||
if (a) {
|
||||
const c_4 = $[4] !== b;
|
||||
const c_5 = $[5] !== c;
|
||||
let y;
|
||||
if (c_4 || c_5) {
|
||||
y = [];
|
||||
if (b) {
|
||||
y.push(c);
|
||||
}
|
||||
$[4] = b;
|
||||
$[5] = c;
|
||||
$[6] = y;
|
||||
} else {
|
||||
y = $[6];
|
||||
}
|
||||
|
||||
x.push(<div>{y}</div>);
|
||||
}
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
$[2] = c;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
function foo(a, b, c) {
|
||||
const x = [];
|
||||
if (a) {
|
||||
const y = [];
|
||||
if (b) {
|
||||
y.push(c);
|
||||
}
|
||||
x.push(<div>{y}</div>);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
const b = [props.b];
|
||||
const c = [props.c];
|
||||
// We don't do constant folding for non-primitive values (yet) so we consider
|
||||
// that any of a, b, or c could return here
|
||||
return (a && b) || c;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(10);
|
||||
const c_0 = $[0] !== props.a;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = [props.a];
|
||||
$[0] = props.a;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const a = t0;
|
||||
const c_2 = $[2] !== props.b;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = [props.b];
|
||||
$[2] = props.b;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const b = t1;
|
||||
const c_4 = $[4] !== props.c;
|
||||
let t2;
|
||||
if (c_4) {
|
||||
t2 = [props.c];
|
||||
$[4] = props.c;
|
||||
$[5] = t2;
|
||||
} else {
|
||||
t2 = $[5];
|
||||
}
|
||||
const c = t2;
|
||||
const c_6 = $[6] !== a;
|
||||
const c_7 = $[7] !== b;
|
||||
const c_8 = $[8] !== c;
|
||||
let t3;
|
||||
if (c_6 || c_7 || c_8) {
|
||||
t3 = (a && b) || c;
|
||||
$[6] = a;
|
||||
$[7] = b;
|
||||
$[8] = c;
|
||||
$[9] = t3;
|
||||
} else {
|
||||
t3 = $[9];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
const b = [props.b];
|
||||
const c = [props.c];
|
||||
// We don't do constant folding for non-primitive values (yet) so we consider
|
||||
// that any of a, b, or c could return here
|
||||
return (a && b) || c;
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
// a can be independently memoized, is not mutated later
|
||||
const a = [props.a];
|
||||
|
||||
// b and c are interleaved and grouped into a single scope,
|
||||
// but they are independent values. c does not escape, but
|
||||
// we need to ensure that a is memoized or else b will invalidate
|
||||
// on every render since a is a dependency.
|
||||
const b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
b.push(props.b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const c_0 = $[0] !== props.a;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = [props.a];
|
||||
$[0] = props.a;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const a = t0;
|
||||
const c_2 = $[2] !== a;
|
||||
const c_3 = $[3] !== props.b;
|
||||
let b;
|
||||
if (c_2 || c_3) {
|
||||
b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
|
||||
b.push(props.b);
|
||||
$[2] = a;
|
||||
$[3] = props.b;
|
||||
$[4] = b;
|
||||
} else {
|
||||
b = $[4];
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
function Component(props) {
|
||||
// a can be independently memoized, is not mutated later
|
||||
const a = [props.a];
|
||||
|
||||
// b and c are interleaved and grouped into a single scope,
|
||||
// but they are independent values. c does not escape, but
|
||||
// we need to ensure that a is memoized or else b will invalidate
|
||||
// on every render since a is a dependency.
|
||||
const b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
b.push(props.b);
|
||||
|
||||
return b;
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
// a does not need to be memoized ever, even though it's a
|
||||
// dependency of c, which exists in a scope that has a memoized
|
||||
// output. it doesn't need to be memoized bc the value is a primitive type.
|
||||
const a = props.a + props.b;
|
||||
|
||||
// b and c are interleaved and grouped into a single scope,
|
||||
// but they are independent values. c does not escape, but
|
||||
// we need to ensure that a is memoized or else b will invalidate
|
||||
// on every render since a is a dependency.
|
||||
const b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
b.push(props.c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
|
||||
const a = props.a + props.b;
|
||||
const c_0 = $[0] !== a;
|
||||
const c_1 = $[1] !== props.c;
|
||||
let b;
|
||||
if (c_0 || c_1) {
|
||||
b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
|
||||
b.push(props.c);
|
||||
$[0] = a;
|
||||
$[1] = props.c;
|
||||
$[2] = b;
|
||||
} else {
|
||||
b = $[2];
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
function Component(props) {
|
||||
// a does not need to be memoized ever, even though it's a
|
||||
// dependency of c, which exists in a scope that has a memoized
|
||||
// output. it doesn't need to be memoized bc the value is a primitive type.
|
||||
const a = props.a + props.b;
|
||||
|
||||
// b and c are interleaved and grouped into a single scope,
|
||||
// but they are independent values. c does not escape, but
|
||||
// we need to ensure that a is memoized or else b will invalidate
|
||||
// on every render since a is a dependency.
|
||||
const b = [];
|
||||
const c = {};
|
||||
c.a = a;
|
||||
b.push(props.c);
|
||||
|
||||
return b;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
const y = x ? props.b : props.c;
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
const y = x ? props.b : props.c;
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
const y = x ? props.b : props.c;
|
||||
return y;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
let y;
|
||||
if (x) {
|
||||
y = props.b;
|
||||
} else {
|
||||
y = props.c;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
let y = undefined;
|
||||
if (x) {
|
||||
y = props.b;
|
||||
} else {
|
||||
y = props.c;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
const x = [props.a];
|
||||
let y;
|
||||
if (x) {
|
||||
y = props.b;
|
||||
} else {
|
||||
y = props.c;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (props.c) {
|
||||
case a: {
|
||||
x = props.d;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (props.c) {
|
||||
case a: {
|
||||
x = props.d;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (props.c) {
|
||||
case a: {
|
||||
x = props.d;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (a) {
|
||||
case true: {
|
||||
x = props.c;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (a) {
|
||||
case true: {
|
||||
x = props.c;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
const a = [props.a];
|
||||
let x = props.b;
|
||||
switch (a) {
|
||||
case true: {
|
||||
x = props.c;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -21,23 +21,14 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props;
|
||||
let y;
|
||||
if (c_0) {
|
||||
y = 0;
|
||||
for (
|
||||
let x = 0;
|
||||
x > props.min && x < props.max;
|
||||
x = x + (props.cond ? props.increment : 2), x
|
||||
) {
|
||||
x = x * 2;
|
||||
y = y + x;
|
||||
}
|
||||
$[0] = props;
|
||||
$[1] = y;
|
||||
} else {
|
||||
y = $[1];
|
||||
let y = 0;
|
||||
for (
|
||||
let x = 0;
|
||||
x > props.min && x < props.max;
|
||||
x = x + (props.cond ? props.increment : 2), x
|
||||
) {
|
||||
x = x * 2;
|
||||
y = y + x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
+2
-22
@@ -28,17 +28,7 @@ function Bar_uncompiled(props) {
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
function Bar_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <div>{props.bar}</div>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
|
||||
export default Bar;
|
||||
@@ -52,17 +42,7 @@ function Foo_uncompiled(props) {
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
function Foo_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <Foo>{props.bar}</Foo>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
|
||||
|
||||
|
||||
+2
-22
@@ -28,17 +28,7 @@ function Bar_uncompiled(props) {
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
function Bar_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <div>{props.bar}</div>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
|
||||
export default Bar;
|
||||
@@ -52,17 +42,7 @@ function Foo_uncompiled(props) {
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
function Foo_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <Foo>{props.bar}</Foo>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
export const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
|
||||
|
||||
|
||||
@@ -28,17 +28,7 @@ function Bar_uncompiled(props) {
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
function Bar_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <div>{props.bar}</div>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
export const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
|
||||
|
||||
@@ -51,17 +41,7 @@ function Foo_uncompiled(props) {
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
function Foo_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <Foo>{props.bar}</Foo>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
export const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
|
||||
|
||||
|
||||
@@ -28,17 +28,7 @@ function Bar_uncompiled(props) {
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
function Bar_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <div>{props.bar}</div>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <div>{props.bar}</div>;
|
||||
}
|
||||
const Bar = isForgetEnabled ? Bar_forget : Bar_uncompiled;
|
||||
|
||||
@@ -51,17 +41,7 @@ function Foo_uncompiled(props) {
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
function Foo_forget(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.bar;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <Foo>{props.bar}</Foo>;
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
return <Foo>{props.bar}</Foo>;
|
||||
}
|
||||
const Foo = isForgetEnabled ? Foo_forget : Foo_uncompiled;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ function useFreeze() {}
|
||||
function foo() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = [];
|
||||
@@ -37,21 +37,12 @@ function Component(props) {
|
||||
const x = t0;
|
||||
const y = useFreeze(x);
|
||||
foo(y, x);
|
||||
const c_1 = $[1] !== y;
|
||||
let t1;
|
||||
if (c_1) {
|
||||
t1 = (
|
||||
<Component>
|
||||
{x}
|
||||
{y}
|
||||
</Component>
|
||||
);
|
||||
$[1] = y;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
return t1;
|
||||
return (
|
||||
<Component>
|
||||
{x}
|
||||
{y}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -56,7 +56,7 @@ function Foo() {}
|
||||
* return = <Foo a={a} b={b} />
|
||||
*/
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== props.b;
|
||||
const c_2 = $[2] !== props.c;
|
||||
@@ -78,18 +78,7 @@ function Component(props) {
|
||||
a = $[3];
|
||||
b = $[4];
|
||||
}
|
||||
const c_5 = $[5] !== a;
|
||||
const c_6 = $[6] !== b;
|
||||
let t0;
|
||||
if (c_5 || c_6) {
|
||||
t0 = <Foo a={a} b={b}></Foo>;
|
||||
$[5] = a;
|
||||
$[6] = b;
|
||||
$[7] = t0;
|
||||
} else {
|
||||
t0 = $[7];
|
||||
}
|
||||
return t0;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -38,7 +38,7 @@ function Foo() {}
|
||||
* return = <Foo a={a} b={b} />
|
||||
*/
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const c_0 = $[0] !== props.a;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
@@ -59,18 +59,7 @@ function Component(props) {
|
||||
t1 = $[3];
|
||||
}
|
||||
const b = t1;
|
||||
const c_4 = $[4] !== a;
|
||||
const c_5 = $[5] !== b;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = <Foo a={a} b={b}></Foo>;
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
function compute() {}
|
||||
|
||||
@@ -45,7 +45,7 @@ function Foo() {}
|
||||
* return = <Foo a={a} b={b} />
|
||||
*/
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== props.b;
|
||||
const c_2 = $[2] !== props.c;
|
||||
@@ -66,18 +66,7 @@ function Component(props) {
|
||||
a = $[3];
|
||||
b = $[4];
|
||||
}
|
||||
const c_5 = $[5] !== a;
|
||||
const c_6 = $[6] !== b;
|
||||
let t0;
|
||||
if (c_5 || c_6) {
|
||||
t0 = <Foo a={a} b={b}></Foo>;
|
||||
$[5] = a;
|
||||
$[6] = b;
|
||||
$[7] = t0;
|
||||
} else {
|
||||
t0 = $[7];
|
||||
}
|
||||
return t0;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -37,7 +37,7 @@ function Foo() {}
|
||||
* return = <Foo a={a} b={b} />
|
||||
*/
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== props.b;
|
||||
let a;
|
||||
@@ -54,18 +54,7 @@ function Component(props) {
|
||||
a = $[2];
|
||||
b = $[3];
|
||||
}
|
||||
const c_4 = $[4] !== a;
|
||||
const c_5 = $[5] !== b;
|
||||
let t0;
|
||||
if (c_4 || c_5) {
|
||||
t0 = <Foo a={a} b={b}></Foo>;
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = t0;
|
||||
} else {
|
||||
t0 = $[6];
|
||||
}
|
||||
return t0;
|
||||
return <Foo a={a} b={b}></Foo>;
|
||||
}
|
||||
|
||||
function compute() {}
|
||||
|
||||
@@ -19,36 +19,12 @@ function Foo(props) {
|
||||
|
||||
```javascript
|
||||
function Foo(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <>Text</>;
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <div>{t0}</div>;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== props.greeting;
|
||||
let t2;
|
||||
if (c_2) {
|
||||
t2 = (
|
||||
<>
|
||||
Hello {props.greeting}
|
||||
{t1}
|
||||
</>
|
||||
);
|
||||
$[2] = props.greeting;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
return (
|
||||
<>
|
||||
Hello {props.greeting}
|
||||
{<div>{<>Text</>}</div>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -14,37 +14,19 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = props.cond ? props.foo : props.bar;
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== t0;
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
|
||||
const t0 = props.cond ? props.foo : props.bar;
|
||||
const c_0 = $[0] !== t0;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
if (c_0) {
|
||||
t1 = { bar: t0 };
|
||||
$[2] = t0;
|
||||
$[3] = t1;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
t1 = $[1];
|
||||
}
|
||||
const c_4 = $[4] !== props;
|
||||
const c_5 = $[5] !== t1;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = <Component {...props} {...t1}></Component>;
|
||||
$[4] = props;
|
||||
$[5] = t1;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
return <Component {...props} {...t1}></Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -19,39 +19,22 @@ function component(props) {
|
||||
|
||||
```javascript
|
||||
function component(props) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== props;
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
|
||||
const a = props.a || (props.b && props.c && props.d);
|
||||
const b = (props.a && props.b && props.c) || props.d;
|
||||
const c_0 = $[0] !== a;
|
||||
const c_1 = $[1] !== b;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = props.a || (props.b && props.c && props.d);
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
if (c_0 || c_1) {
|
||||
t0 = { a, b };
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
t0 = $[2];
|
||||
}
|
||||
const a = t0;
|
||||
const c_2 = $[2] !== props;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = (props.a && props.b && props.c) || props.d;
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const b = t1;
|
||||
const c_4 = $[4] !== a;
|
||||
const c_5 = $[5] !== b;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = { a, b };
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -14,41 +14,9 @@ function component(props) {
|
||||
|
||||
```javascript
|
||||
function component(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = props.a || (props.b && props.c && props.d);
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const a = t0;
|
||||
const c_2 = $[2] !== props;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = (props.a && props.b && props.c) || props.d;
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const b = t1;
|
||||
const c_4 = $[4] !== a;
|
||||
const c_5 = $[5] !== b;
|
||||
const c_6 = $[6] !== props;
|
||||
let t2;
|
||||
if (c_4 || c_5 || c_6) {
|
||||
t2 = a ? b : props.c;
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = props;
|
||||
$[7] = t2;
|
||||
} else {
|
||||
t2 = $[7];
|
||||
}
|
||||
return t2;
|
||||
const a = props.a || (props.b && props.c && props.d);
|
||||
const b = (props.a && props.b && props.c) || props.d;
|
||||
return a ? b : props.c;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -41,17 +41,9 @@ function mutate() {}
|
||||
function cond() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
const a = {};
|
||||
const b = {};
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = {};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const c = t0;
|
||||
const c = {};
|
||||
const d = {};
|
||||
while (true) {
|
||||
mutate(a, b);
|
||||
|
||||
+3
-11
@@ -21,7 +21,7 @@ function foo(a, b, c) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const $ = React.unstable_useMemoCache(9);
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== a;
|
||||
const c_1 = $[1] !== b;
|
||||
const c_2 = $[2] !== c;
|
||||
@@ -43,16 +43,8 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
y = $[6];
|
||||
}
|
||||
const c_7 = $[7] !== y;
|
||||
let t0;
|
||||
if (c_7) {
|
||||
t0 = <div>{y}</div>;
|
||||
$[7] = y;
|
||||
$[8] = t0;
|
||||
} else {
|
||||
t0 = $[8];
|
||||
}
|
||||
x.push(t0);
|
||||
|
||||
x.push(<div>{y}</div>);
|
||||
}
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
|
||||
@@ -17,7 +17,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props.p0;
|
||||
let x;
|
||||
let child;
|
||||
@@ -35,18 +35,7 @@ function Component(props) {
|
||||
x = $[1];
|
||||
child = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== x;
|
||||
const c_4 = $[4] !== child;
|
||||
let t0;
|
||||
if (c_3 || c_4) {
|
||||
t0 = <Component data={x}>{child}</Component>;
|
||||
$[3] = x;
|
||||
$[4] = child;
|
||||
$[5] = t0;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
}
|
||||
return t0;
|
||||
return <Component data={x}>{child}</Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ function foo(a, b, c) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const c_0 = $[0] !== a;
|
||||
const c_1 = $[1] !== b;
|
||||
const c_2 = $[2] !== c;
|
||||
@@ -38,16 +38,7 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
y = $[5];
|
||||
}
|
||||
const c_6 = $[6] !== y;
|
||||
let t0;
|
||||
if (c_6) {
|
||||
t0 = <div>{y}</div>;
|
||||
$[6] = y;
|
||||
$[7] = t0;
|
||||
} else {
|
||||
t0 = $[7];
|
||||
}
|
||||
x.push(t0);
|
||||
x.push(<div>{y}</div>);
|
||||
} else {
|
||||
x.push(c);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ function f(a, b) {
|
||||
|
||||
```javascript
|
||||
function f(a, b) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== a.length;
|
||||
const c_1 = $[1] !== b;
|
||||
let x;
|
||||
@@ -36,16 +36,7 @@ function f(a, b) {
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== x;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = <div>{x}</div>;
|
||||
$[3] = x;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
return t0;
|
||||
return <div>{x}</div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -23,7 +23,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props.p0;
|
||||
let x;
|
||||
if (c_0) {
|
||||
@@ -47,18 +47,7 @@ function Component(props) {
|
||||
}
|
||||
|
||||
y.push(props.p2);
|
||||
const c_3 = $[3] !== x;
|
||||
const c_4 = $[4] !== y;
|
||||
let t1;
|
||||
if (c_3 || c_4) {
|
||||
t1 = <Component x={x} y={y}></Component>;
|
||||
$[3] = x;
|
||||
$[4] = y;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
return <Component x={x} y={y}></Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -34,7 +34,7 @@ function foo(a, b, c) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const $ = React.unstable_useMemoCache(11);
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const c_0 = $[0] !== a;
|
||||
let x;
|
||||
if (c_0) {
|
||||
@@ -47,58 +47,39 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== x;
|
||||
let t0;
|
||||
if (c_2) {
|
||||
t0 = <div>{x}</div>;
|
||||
$[2] = x;
|
||||
$[3] = t0;
|
||||
} else {
|
||||
t0 = $[3];
|
||||
}
|
||||
const y = t0;
|
||||
|
||||
const y = <div>{x}</div>;
|
||||
bb3: switch (b) {
|
||||
case 0: {
|
||||
const c_4 = $[4] !== b;
|
||||
if (c_4) {
|
||||
const c_2 = $[2] !== b;
|
||||
if (c_2) {
|
||||
x = [];
|
||||
x.push(b);
|
||||
$[4] = b;
|
||||
$[5] = x;
|
||||
$[2] = b;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[5];
|
||||
x = $[3];
|
||||
}
|
||||
break bb3;
|
||||
}
|
||||
default: {
|
||||
const c_6 = $[6] !== c;
|
||||
if (c_6) {
|
||||
const c_4 = $[4] !== c;
|
||||
if (c_4) {
|
||||
x = [];
|
||||
x.push(c);
|
||||
$[6] = c;
|
||||
$[7] = x;
|
||||
$[4] = c;
|
||||
$[5] = x;
|
||||
} else {
|
||||
x = $[7];
|
||||
x = $[5];
|
||||
}
|
||||
}
|
||||
}
|
||||
const c_8 = $[8] !== y;
|
||||
const c_9 = $[9] !== x;
|
||||
let t1;
|
||||
if (c_8 || c_9) {
|
||||
t1 = (
|
||||
<div>
|
||||
{y}
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
$[8] = y;
|
||||
$[9] = x;
|
||||
$[10] = t1;
|
||||
} else {
|
||||
t1 = $[10];
|
||||
}
|
||||
return t1;
|
||||
return (
|
||||
<div>
|
||||
{y}
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -21,7 +21,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const c_0 = $[0] !== props.p0;
|
||||
const c_1 = $[1] !== props.p1;
|
||||
let x;
|
||||
@@ -48,18 +48,7 @@ function Component(props) {
|
||||
x = $[2];
|
||||
y = $[3];
|
||||
}
|
||||
const c_5 = $[5] !== x;
|
||||
const c_6 = $[6] !== y;
|
||||
let t1;
|
||||
if (c_5 || c_6) {
|
||||
t1 = <Component x={x} y={y}></Component>;
|
||||
$[5] = x;
|
||||
$[6] = y;
|
||||
$[7] = t1;
|
||||
} else {
|
||||
t1 = $[7];
|
||||
}
|
||||
return t1;
|
||||
return <Component x={x} y={y}></Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+2
-11
@@ -26,22 +26,13 @@ function TestCondDepInDirectIfElse(props, other) {
|
||||
// paths
|
||||
|
||||
function TestCondDepInDirectIfElse(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props.a.b;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.b = props.a.b;
|
||||
} else {
|
||||
x.c = props.a.b;
|
||||
|
||||
+3
-19
@@ -26,30 +26,14 @@ function TestCondDepInNestedIfElse(props, other) {
|
||||
// scope that produces x if it is not accessed in every path
|
||||
|
||||
function TestCondDepInNestedIfElse(props, other) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
let t1;
|
||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = bar();
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
if (t1) {
|
||||
if (foo(other)) {
|
||||
if (bar()) {
|
||||
x.a = props.a.b;
|
||||
}
|
||||
} else {
|
||||
|
||||
+4
-29
@@ -32,45 +32,20 @@ function TestCondDepInNestedIfElse(props, other) {
|
||||
// paths
|
||||
|
||||
function TestCondDepInNestedIfElse(props, other) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props.a.b;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
let t1;
|
||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = bar();
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
if (t1) {
|
||||
if (foo(other)) {
|
||||
if (bar()) {
|
||||
x.a = props.a.b;
|
||||
} else {
|
||||
x.b = props.a.b;
|
||||
}
|
||||
} else {
|
||||
const c_6 = $[6] !== other;
|
||||
let t2;
|
||||
if (c_6) {
|
||||
t2 = baz(other);
|
||||
$[6] = other;
|
||||
$[7] = t2;
|
||||
} else {
|
||||
t2 = $[7];
|
||||
}
|
||||
if (t2) {
|
||||
if (baz(other)) {
|
||||
x.c = props.a.b;
|
||||
} else {
|
||||
x.d = props.a.b;
|
||||
|
||||
+2
-11
@@ -30,22 +30,13 @@ function TestCondDepInSwitchMissingCase(props, other) {
|
||||
// scope that produces x if it is not accessed in every path
|
||||
|
||||
function TestCondDepInSwitchMissingCase(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
bb1: switch (t0) {
|
||||
bb1: switch (foo(other)) {
|
||||
case 1: {
|
||||
x.a = props.a.b;
|
||||
break bb1;
|
||||
|
||||
+2
-11
@@ -27,22 +27,13 @@ function TestCondDepInSwitchMissingDefault(props, other) {
|
||||
// scope that produces x if it is not accessed in the default case.
|
||||
|
||||
function TestCondDepInSwitchMissingDefault(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
bb1: switch (t0) {
|
||||
bb1: switch (foo(other)) {
|
||||
case 1: {
|
||||
x.a = props.a.b;
|
||||
break bb1;
|
||||
|
||||
+2
-11
@@ -31,22 +31,13 @@ function TestCondDepInSwitch(props, other) {
|
||||
// paths
|
||||
|
||||
function TestCondDepInSwitch(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props.a.b;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
bb1: switch (t0) {
|
||||
bb1: switch (foo(other)) {
|
||||
case 1: {
|
||||
x.a = props.a.b;
|
||||
break bb1;
|
||||
|
||||
+2
-11
@@ -21,22 +21,13 @@ function TestOnlyConditionalDependencies(props, other) {
|
||||
// When an object's properties are only read conditionally, we should
|
||||
// track the base object as a dependency.
|
||||
function TestOnlyConditionalDependencies(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.b = props.a.b;
|
||||
x.c = props.a.b.c;
|
||||
}
|
||||
|
||||
+2
-11
@@ -23,23 +23,14 @@ function TestPromoteUnconditionalAccessToDependency(props, other) {
|
||||
// in its subpath or superpath, we should find the nearest unconditional access
|
||||
// and promote it to an unconditional dependency.
|
||||
function TestPromoteUnconditionalAccessToDependency(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== other;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
x.a = props.a.a.a;
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.c = props.a.b.c;
|
||||
}
|
||||
$[0] = props.a;
|
||||
|
||||
+2
-11
@@ -27,23 +27,14 @@ function TestConditionalSubpath1(props, other) {
|
||||
// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`
|
||||
// ordering of accesses should not matter
|
||||
function TestConditionalSubpath1(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== other;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
x.b = props.a.b;
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.a = props.a;
|
||||
}
|
||||
$[0] = props.a;
|
||||
|
||||
+2
-11
@@ -27,22 +27,13 @@ function TestConditionalSubpath2(props, other) {
|
||||
// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`
|
||||
// ordering of accesses should not matter
|
||||
function TestConditionalSubpath2(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props.a;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.a = props.a;
|
||||
}
|
||||
x.b = props.a.b;
|
||||
|
||||
+2
-11
@@ -25,23 +25,14 @@ function TestConditionalSuperpath1(props, other) {
|
||||
// as a dependency
|
||||
// ordering of accesses should not matter
|
||||
function TestConditionalSuperpath1(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props.a;
|
||||
const c_1 = $[1] !== other;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
x.a = props.a;
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.b = props.a.b;
|
||||
}
|
||||
$[0] = props.a;
|
||||
|
||||
+2
-11
@@ -25,22 +25,13 @@ function TestConditionalSuperpath2(props, other) {
|
||||
// as a dependency
|
||||
// ordering of accesses should not matter
|
||||
function TestConditionalSuperpath2(props, other) {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== other;
|
||||
const c_1 = $[1] !== props.a;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
const c_3 = $[3] !== other;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = foo(other);
|
||||
$[3] = other;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo(other)) {
|
||||
x.b = props.a.b;
|
||||
}
|
||||
x.a = props.a;
|
||||
|
||||
+27
-58
@@ -46,7 +46,7 @@ function foo(props) {
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(16);
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== props.a;
|
||||
let x;
|
||||
if (c_0) {
|
||||
@@ -57,70 +57,39 @@ function foo(props) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== props.showHeader;
|
||||
const c_3 = $[3] !== x;
|
||||
let t0;
|
||||
if (c_2 || c_3) {
|
||||
t0 = props.showHeader ? <div>{x}</div> : null;
|
||||
$[2] = props.showHeader;
|
||||
$[3] = x;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
const header = t0;
|
||||
const c_5 = $[5] !== x;
|
||||
const c_6 = $[6] !== props.b;
|
||||
const c_7 = $[7] !== props.c;
|
||||
|
||||
const header = props.showHeader ? <div>{x}</div> : null;
|
||||
const c_2 = $[2] !== x;
|
||||
const c_3 = $[3] !== props.b;
|
||||
const c_4 = $[4] !== props.c;
|
||||
let y;
|
||||
if (c_5 || c_6 || c_7) {
|
||||
if (c_2 || c_3 || c_4) {
|
||||
y = [x];
|
||||
x = [];
|
||||
y.push(props.b);
|
||||
x.push(props.c);
|
||||
$[5] = x;
|
||||
$[6] = props.b;
|
||||
$[7] = props.c;
|
||||
$[8] = y;
|
||||
$[9] = x;
|
||||
$[2] = x;
|
||||
$[3] = props.b;
|
||||
$[4] = props.c;
|
||||
$[5] = y;
|
||||
$[6] = x;
|
||||
} else {
|
||||
y = $[8];
|
||||
x = $[9];
|
||||
y = $[5];
|
||||
x = $[6];
|
||||
}
|
||||
const c_10 = $[10] !== x;
|
||||
const c_11 = $[11] !== y;
|
||||
let t1;
|
||||
if (c_10 || c_11) {
|
||||
t1 = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
$[10] = x;
|
||||
$[11] = y;
|
||||
$[12] = t1;
|
||||
} else {
|
||||
t1 = $[12];
|
||||
}
|
||||
const content = t1;
|
||||
const c_13 = $[13] !== header;
|
||||
const c_14 = $[14] !== content;
|
||||
let t2;
|
||||
if (c_13 || c_14) {
|
||||
t2 = (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
$[13] = header;
|
||||
$[14] = content;
|
||||
$[15] = t2;
|
||||
} else {
|
||||
t2 = $[15];
|
||||
}
|
||||
return t2;
|
||||
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+26
-55
@@ -46,7 +46,7 @@ function foo(props) {
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(15);
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== props.a;
|
||||
let x;
|
||||
if (c_0) {
|
||||
@@ -57,68 +57,39 @@ function foo(props) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
|
||||
const header = <div>{x}</div>;
|
||||
const c_2 = $[2] !== x;
|
||||
let t0;
|
||||
if (c_2) {
|
||||
t0 = <div>{x}</div>;
|
||||
$[2] = x;
|
||||
$[3] = t0;
|
||||
} else {
|
||||
t0 = $[3];
|
||||
}
|
||||
const header = t0;
|
||||
const c_4 = $[4] !== x;
|
||||
const c_5 = $[5] !== props.b;
|
||||
const c_6 = $[6] !== props.c;
|
||||
const c_3 = $[3] !== props.b;
|
||||
const c_4 = $[4] !== props.c;
|
||||
let y;
|
||||
if (c_4 || c_5 || c_6) {
|
||||
if (c_2 || c_3 || c_4) {
|
||||
y = [x];
|
||||
x = [];
|
||||
y.push(props.b);
|
||||
x.push(props.c);
|
||||
$[4] = x;
|
||||
$[5] = props.b;
|
||||
$[6] = props.c;
|
||||
$[7] = y;
|
||||
$[8] = x;
|
||||
$[2] = x;
|
||||
$[3] = props.b;
|
||||
$[4] = props.c;
|
||||
$[5] = y;
|
||||
$[6] = x;
|
||||
} else {
|
||||
y = $[7];
|
||||
x = $[8];
|
||||
y = $[5];
|
||||
x = $[6];
|
||||
}
|
||||
const c_9 = $[9] !== x;
|
||||
const c_10 = $[10] !== y;
|
||||
let t1;
|
||||
if (c_9 || c_10) {
|
||||
t1 = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
$[9] = x;
|
||||
$[10] = y;
|
||||
$[11] = t1;
|
||||
} else {
|
||||
t1 = $[11];
|
||||
}
|
||||
const content = t1;
|
||||
const c_12 = $[12] !== header;
|
||||
const c_13 = $[13] !== content;
|
||||
let t2;
|
||||
if (c_12 || c_13) {
|
||||
t2 = (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
$[12] = header;
|
||||
$[13] = content;
|
||||
$[14] = t2;
|
||||
} else {
|
||||
t2 = $[14];
|
||||
}
|
||||
return t2;
|
||||
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -25,21 +25,14 @@ function Component(props) {
|
||||
function foo() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let a;
|
||||
let b;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
a = [];
|
||||
b = {};
|
||||
foo(a, b);
|
||||
let t0;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = foo();
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
if (t0) {
|
||||
if (foo()) {
|
||||
}
|
||||
|
||||
foo(a, b);
|
||||
@@ -49,14 +42,7 @@ function Component(props) {
|
||||
a = $[0];
|
||||
b = $[1];
|
||||
}
|
||||
let t1;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <div a={a} b={b}></div>;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
return <div a={a} b={b}></div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -21,7 +21,7 @@ function Component(props) {
|
||||
function foo() {}
|
||||
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let a;
|
||||
let b;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
@@ -36,14 +36,7 @@ function Component(props) {
|
||||
a = $[0];
|
||||
b = $[1];
|
||||
}
|
||||
let t0;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <div a={a} b={b}></div>;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
return <div a={a} b={b}></div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -24,22 +24,13 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let x = 0;
|
||||
const c_0 = $[0] !== props;
|
||||
let values;
|
||||
if (c_0) {
|
||||
values = [];
|
||||
const c_2 = $[2] !== props;
|
||||
let t0;
|
||||
if (c_2) {
|
||||
t0 = props.a || props.b;
|
||||
$[2] = props;
|
||||
$[3] = t0;
|
||||
} else {
|
||||
t0 = $[3];
|
||||
}
|
||||
const y = t0;
|
||||
const y = props.a || props.b;
|
||||
values.push(y);
|
||||
if (props.c) {
|
||||
x = 1;
|
||||
|
||||
@@ -16,16 +16,9 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = 1;
|
||||
for (const i = 0; true; 0) {
|
||||
x = x + 1;
|
||||
}
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
let x = 1;
|
||||
for (const i = 0; true; 0) {
|
||||
x = x + 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -16,16 +16,9 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = 1;
|
||||
for (let i = 0; i < 10; i = i + 1, i) {
|
||||
x = x + 1;
|
||||
}
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
let x = 1;
|
||||
for (let i = 0; i < 10; i = i + 1, i) {
|
||||
x = x + 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props;
|
||||
let x;
|
||||
let y;
|
||||
@@ -41,23 +41,12 @@ function Component(props) {
|
||||
x = $[1];
|
||||
y = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== x;
|
||||
const c_4 = $[4] !== y;
|
||||
let t0;
|
||||
if (c_3 || c_4) {
|
||||
t0 = (
|
||||
<Component>
|
||||
{x}
|
||||
{y}
|
||||
</Component>
|
||||
);
|
||||
$[3] = x;
|
||||
$[4] = y;
|
||||
$[5] = t0;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
}
|
||||
return t0;
|
||||
return (
|
||||
<Component>
|
||||
{x}
|
||||
{y}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -17,16 +17,9 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = 1;
|
||||
while (x < 10) {
|
||||
x = x + 1;
|
||||
}
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
let x = 1;
|
||||
while (x < 10) {
|
||||
x = x + 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(9);
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const c_0 = $[0] !== props;
|
||||
let x;
|
||||
let y;
|
||||
@@ -69,29 +69,10 @@ function Component(props) {
|
||||
x = $[1];
|
||||
y = $[2];
|
||||
}
|
||||
const c_4 = $[4] !== x;
|
||||
let t1;
|
||||
if (c_4) {
|
||||
t1 = <Component data={x}></Component>;
|
||||
$[4] = x;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
const child = t1;
|
||||
|
||||
const child = <Component data={x}></Component>;
|
||||
y.push(props.p4);
|
||||
const c_6 = $[6] !== y;
|
||||
const c_7 = $[7] !== child;
|
||||
let t2;
|
||||
if (c_6 || c_7) {
|
||||
t2 = <Component data={y}>{child}</Component>;
|
||||
$[6] = y;
|
||||
$[7] = child;
|
||||
$[8] = t2;
|
||||
} else {
|
||||
t2 = $[8];
|
||||
}
|
||||
return t2;
|
||||
return <Component data={y}>{child}</Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -27,7 +27,7 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== props;
|
||||
let x;
|
||||
let y;
|
||||
@@ -50,29 +50,10 @@ function Component(props) {
|
||||
x = $[1];
|
||||
y = $[2];
|
||||
}
|
||||
const c_3 = $[3] !== x;
|
||||
let t0;
|
||||
if (c_3) {
|
||||
t0 = <Component data={x}></Component>;
|
||||
$[3] = x;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
const child = t0;
|
||||
|
||||
const child = <Component data={x}></Component>;
|
||||
y.push(props.p4);
|
||||
const c_5 = $[5] !== y;
|
||||
const c_6 = $[6] !== child;
|
||||
let t1;
|
||||
if (c_5 || c_6) {
|
||||
t1 = <Component data={y}>{child}</Component>;
|
||||
$[5] = y;
|
||||
$[6] = child;
|
||||
$[7] = t1;
|
||||
} else {
|
||||
t1 = $[7];
|
||||
}
|
||||
return t1;
|
||||
return <Component data={y}>{child}</Component>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+1
-11
@@ -14,17 +14,7 @@ function component(props) {
|
||||
|
||||
```javascript
|
||||
function component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const x = t0;
|
||||
const x = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,39 +14,9 @@ function ternary(props) {
|
||||
|
||||
```javascript
|
||||
function ternary(props) {
|
||||
const $ = React.unstable_useMemoCache(7);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = props.a && props.b ? props.c || props.d : props.e ?? props.f;
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const a = t0;
|
||||
const c_2 = $[2] !== props;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const b = t1;
|
||||
const c_4 = $[4] !== a;
|
||||
const c_5 = $[5] !== b;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = a ? b : null;
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
const a = props.a && props.b ? props.c || props.d : props.e ?? props.f;
|
||||
const b = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
|
||||
return a ? b : null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -19,43 +19,22 @@ function Component(props) {
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
const start = performance.now();
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = performance.now();
|
||||
t0 = Date.now();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const start = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = Date.now();
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const now = t1;
|
||||
let t2;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = performance.now();
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
const time = t2 - start;
|
||||
let t3;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t3 = (
|
||||
<div>
|
||||
rendering took {time} at {now}
|
||||
</div>
|
||||
);
|
||||
$[3] = t3;
|
||||
} else {
|
||||
t3 = $[3];
|
||||
}
|
||||
return t3;
|
||||
const now = t0;
|
||||
const time = performance.now() - start;
|
||||
return (
|
||||
<div>
|
||||
rendering took {time} at {now}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -16,23 +16,8 @@ function component() {
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = some();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const a = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = someOther();
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const b = t1;
|
||||
const a = some();
|
||||
const b = someOther();
|
||||
if (a > b) {
|
||||
}
|
||||
}
|
||||
|
||||
+6
-20
@@ -19,7 +19,11 @@ function component() {
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
const x = foo();
|
||||
const y = foo();
|
||||
if (x > y) {
|
||||
}
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = foo();
|
||||
@@ -27,25 +31,7 @@ function component() {
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = foo();
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const y = t1;
|
||||
if (x > y) {
|
||||
}
|
||||
let t2;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = foo();
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
const z_0 = t2;
|
||||
const z_0 = t0;
|
||||
return z_0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,58 +20,37 @@ function component(a) {
|
||||
|
||||
```javascript
|
||||
function component(a) {
|
||||
const $ = React.unstable_useMemoCache(14);
|
||||
const c_0 = $[0] !== a;
|
||||
let t0;
|
||||
let t;
|
||||
let z;
|
||||
let p;
|
||||
let q;
|
||||
if (c_0) {
|
||||
t = { t: a };
|
||||
z = +t.t;
|
||||
q = -t.t;
|
||||
p = void t.t;
|
||||
t0 = delete t.t;
|
||||
$[0] = a;
|
||||
$[1] = t0;
|
||||
$[2] = t;
|
||||
$[3] = z;
|
||||
$[4] = p;
|
||||
$[5] = q;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
t = $[2];
|
||||
z = $[3];
|
||||
p = $[4];
|
||||
q = $[5];
|
||||
}
|
||||
const n = t0;
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const t = { t: a };
|
||||
const z = +t.t;
|
||||
const q = -t.t;
|
||||
const p = void t.t;
|
||||
const n = delete t.t;
|
||||
const m = !t.t;
|
||||
const e = ~t.t;
|
||||
const f = typeof t.t;
|
||||
const c_6 = $[6] !== z;
|
||||
const c_7 = $[7] !== p;
|
||||
const c_8 = $[8] !== q;
|
||||
const c_9 = $[9] !== n;
|
||||
const c_10 = $[10] !== m;
|
||||
const c_11 = $[11] !== e;
|
||||
const c_12 = $[12] !== f;
|
||||
let t1;
|
||||
if (c_6 || c_7 || c_8 || c_9 || c_10 || c_11 || c_12) {
|
||||
t1 = { z, p, q, n, m, e, f };
|
||||
$[6] = z;
|
||||
$[7] = p;
|
||||
$[8] = q;
|
||||
$[9] = n;
|
||||
$[10] = m;
|
||||
$[11] = e;
|
||||
$[12] = f;
|
||||
$[13] = t1;
|
||||
const c_0 = $[0] !== z;
|
||||
const c_1 = $[1] !== p;
|
||||
const c_2 = $[2] !== q;
|
||||
const c_3 = $[3] !== n;
|
||||
const c_4 = $[4] !== m;
|
||||
const c_5 = $[5] !== e;
|
||||
const c_6 = $[6] !== f;
|
||||
let t0;
|
||||
if (c_0 || c_1 || c_2 || c_3 || c_4 || c_5 || c_6) {
|
||||
t0 = { z, p, q, n, m, e, f };
|
||||
$[0] = z;
|
||||
$[1] = p;
|
||||
$[2] = q;
|
||||
$[3] = n;
|
||||
$[4] = m;
|
||||
$[5] = e;
|
||||
$[6] = f;
|
||||
$[7] = t0;
|
||||
} else {
|
||||
t1 = $[13];
|
||||
t0 = $[7];
|
||||
}
|
||||
return t1;
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@ function component() {
|
||||
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.unstable_useMemoCache(5);
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const [count, setCount] = useState(0);
|
||||
const c_0 = $[0] !== setCount;
|
||||
const c_1 = $[1] !== count;
|
||||
@@ -29,16 +29,7 @@ function component() {
|
||||
t0 = $[2];
|
||||
}
|
||||
const increment = t0;
|
||||
const c_3 = $[3] !== increment;
|
||||
let t1;
|
||||
if (c_3) {
|
||||
t1 = <Foo onClick={increment}></Foo>;
|
||||
$[3] = increment;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
return t1;
|
||||
return <Foo onClick={increment}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -13,7 +13,7 @@ function component(a) {
|
||||
|
||||
```javascript
|
||||
function component(a) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== a;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
@@ -24,16 +24,7 @@ function component(a) {
|
||||
t0 = $[1];
|
||||
}
|
||||
const x = t0;
|
||||
const c_2 = $[2] !== x;
|
||||
let t1;
|
||||
if (c_2) {
|
||||
t1 = <Foo x={x}></Foo>;
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
return <Foo x={x}></Foo>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -16,20 +16,9 @@ function foo(a, b) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b) {
|
||||
const $ = React.unstable_useMemoCache(3);
|
||||
const c_0 = $[0] !== a.b.c;
|
||||
const c_1 = $[1] !== b;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = 0;
|
||||
while (a.b.c) {
|
||||
x = x + b;
|
||||
}
|
||||
$[0] = a.b.c;
|
||||
$[1] = b;
|
||||
$[2] = x;
|
||||
} else {
|
||||
x = $[2];
|
||||
let x = 0;
|
||||
while (a.b.c) {
|
||||
x = x + b;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user