Compare commits

..

1 Commits

Author SHA1 Message Date
Joe Savona
32e058e01f [compiler] New inference repros/fixes
Substantially improves the last major known issue with the new inference model's implementation: inferring effects of function expressions. I knowingly used a really simple (dumb) approach in InferFunctionExpressionAliasingEffects but it worked surprisingly well on a ton of code. However, investigating during the sync I saw that we the algorithm was literally running out of memory, or crashing from arrays that exceeded the maximum capacity. We were accumluating data flow in a way that could lead to lists of data flow captures compounding on themselves and growing very large very quickly. Plus, we were incorrectly recording some data flow, leading to cases where we reported false positive "can't mutate frozen value" for example.

So I went back to the drawing board. InferMutationAliasingRanges already builds up a data flow graph which it uses to figure out what values would be affected by mutations of other values, and update mutable ranges. Well, the key question that we really want to answer for inferring a function expression's aliasing effects is which values alias/capture where. Per the docs I wrote up, we only have to record such aliasing _if they are observable via mutations_. So, lightbulb: simulate mutations of the params, free variables, and return of the function expression and see which params/free-vars would be affected! That's what we do now, giving us precise information about which such values alias/capture where. When the "into" is a param/context-var we use Capture, iwhen the destination is the return we use Alias to be conservative.
2025-06-23 14:22:16 -07:00
275 changed files with 6020 additions and 9624 deletions

View File

@@ -622,7 +622,6 @@ module.exports = {
ScrollTimeline: 'readonly',
EventListenerOptionsOrUseCapture: 'readonly',
FocusOptions: 'readonly',
OptionalEffectTiming: 'readonly',
spyOnDev: 'readonly',
spyOnDevAndProd: 'readonly',

View File

@@ -301,12 +301,10 @@ jobs:
path: |
**/node_modules
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
- name: Install runtime dependencies
run: yarn install --frozen-lockfile
if: steps.node_modules.outputs.cache-hit != 'true'
- name: Install compiler dependencies
run: yarn install --frozen-lockfile
working-directory: compiler
restore-keys: |
runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-
runtime-and-compiler-node_modules-v6-
- run: yarn install --frozen-lockfile
if: steps.node_modules.outputs.cache-hit != 'true'
- run: ./scripts/react-compiler/build-compiler.sh && ./scripts/react-compiler/link-compiler.sh
- run: yarn workspace eslint-plugin-react-hooks test

View File

@@ -85,7 +85,7 @@ jobs:
--skipTests \
--tags=${{ inputs.dist_tag }} \
--onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}}
${{ inputs.dry && '--dry' || '' }}
${{ inputs.dry && '--dry'}}
- if: '${{ inputs.skip_packages }}'
name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'
run: |
@@ -94,19 +94,19 @@ jobs:
--skipTests \
--tags=${{ inputs.dist_tag }} \
--skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}}
${{ inputs.dry && '--dry' || '' }}
${{ inputs.dry && '--dry'}}
- if: '${{ !(inputs.skip_packages && inputs.only_packages) }}'
name: 'Publish all packages'
run: |
scripts/release/publish.js \
--ci \
--tags=${{ inputs.dist_tag }} ${{ (inputs.dry && '') || '\'}}
${{ inputs.dry && '--dry' || '' }}
${{ inputs.dry && '--dry'}}
- name: Notify Discord on failure
if: failure() && inputs.enableFailureNotification == true
uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
embed-author-name: "GitHub Actions"
embed-title: '[Runtime] Publish of ${{ inputs.release_channel }}@${{ inputs.dist_tag}} release failed'
embed-title: 'Publish of $${{ inputs.release_channel }} release failed'
embed-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}

View File

@@ -110,7 +110,7 @@ jobs:
--tags=${{ inputs.tags }} \
--publishVersion=${{ inputs.version_to_publish }} \
--onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}}
${{ inputs.dry && '--dry' || '' }}
${{ inputs.dry && '--dry'}}
- if: '${{ inputs.skip_packages }}'
name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'
run: |
@@ -119,7 +119,7 @@ jobs:
--tags=${{ inputs.tags }} \
--publishVersion=${{ inputs.version_to_publish }} \
--skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}}
${{ inputs.dry && '--dry' || '' }}
${{ inputs.dry && '--dry'}}
- name: Archive released package for debugging
uses: actions/upload-artifact@v4
with:

View File

@@ -19,11 +19,11 @@ An Owner Stack is a string representing the components that are directly respons
* Updated `useId` to use valid CSS selectors, changing format from `:r123:` to `«r123»`. [#32001](https://github.com/facebook/react/pull/32001)
* Added a dev-only warning for null/undefined created in useEffect, useInsertionEffect, and useLayoutEffect. [#32355](https://github.com/facebook/react/pull/32355)
* Fixed a bug where dev-only methods were exported in production builds. React.act is no longer available in production builds. [#32200](https://github.com/facebook/react/pull/32200)
* Improved consistency across prod and dev to improve compatibility with Google Closure Compiler and bindings [#31808](https://github.com/facebook/react/pull/31808)
* Improved consistency across prod and dev to improve compatibility with Google Closure Complier and bindings [#31808](https://github.com/facebook/react/pull/31808)
* Improve passive effect scheduling for consistent task yielding. [#31785](https://github.com/facebook/react/pull/31785)
* Fixed asserts in React Native when passChildrenWhenCloningPersistedNodes is enabled for OffscreenComponent rendering. [#32528](https://github.com/facebook/react/pull/32528)
* Fixed component name resolution for Portal [#32640](https://github.com/facebook/react/pull/32640)
* Added support for beforetoggle and toggle events on the dialog element. [#32479](https://github.com/facebook/react/pull/32479)
* Added support for beforetoggle and toggle events on the dialog element. #32479 [#32479](https://github.com/facebook/react/pull/32479)
### React DOM
* Fixed double warning when the `href` attribute is an empty string [#31783](https://github.com/facebook/react/pull/31783)

View File

@@ -44,7 +44,6 @@ import {
PrintedCompilerPipelineValue,
} from './Output';
import {transformFromAstSync} from '@babel/core';
import {LoggerEvent} from 'babel-plugin-react-compiler/dist/Entrypoint';
function parseInput(
input: string,
@@ -144,7 +143,6 @@ const COMMON_HOOKS: Array<[string, Hook]> = [
function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
const results = new Map<string, Array<PrintedCompilerPipelineValue>>();
const error = new CompilerError();
const otherErrors: Array<CompilerErrorDetail> = [];
const upsert: (result: PrintedCompilerPipelineValue) => void = result => {
const entry = results.get(result.name);
if (Array.isArray(entry)) {
@@ -212,11 +210,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
},
logger: {
debugLogIRs: logIR,
logEvent: (_filename: string | null, event: LoggerEvent) => {
if (event.kind === 'CompileError') {
otherErrors.push(new CompilerErrorDetail(event.detail));
}
},
logEvent: () => {},
},
});
transformOutput = invokeCompiler(source, language, opts);
@@ -243,10 +237,6 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
);
}
}
// Only include logger errors if there weren't other errors
if (!error.hasErrors() && otherErrors.length !== 0) {
otherErrors.forEach(e => error.push(e));
}
if (error.hasErrors()) {
return [{kind: 'err', results, error: error}, language];
}

View File

@@ -221,6 +221,7 @@ export function lower(
params,
fnType: bindings == null ? env.fnType : 'Other',
returnTypeAnnotation: null, // TODO: extract the actual return type node if present
returnType: makeType(),
returns: createTemporaryPlace(env, func.node.loc ?? GeneratedSource),
body: builder.build(),
context,
@@ -1355,45 +1356,13 @@ function lowerStatement(
return;
}
case 'WithStatement': {
builder.errors.push({
reason: `JavaScript 'with' syntax is not supported`,
description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`,
severity: ErrorSeverity.InvalidJS,
loc: stmtPath.node.loc ?? null,
suggestions: null,
});
lowerValueToTemporary(builder, {
kind: 'UnsupportedNode',
loc: stmtPath.node.loc ?? GeneratedSource,
node: stmtPath.node,
});
return;
}
case 'ClassDeclaration': {
/*
* We can in theory support nested classes, similarly to functions where we track values
* captured by the class and consider mutations of the instances to mutate the class itself
*/
builder.errors.push({
reason: `Support nested class declarations`,
severity: ErrorSeverity.Todo,
loc: stmtPath.node.loc ?? null,
suggestions: null,
});
lowerValueToTemporary(builder, {
kind: 'UnsupportedNode',
loc: stmtPath.node.loc ?? GeneratedSource,
node: stmtPath.node,
});
return;
}
case 'TypeAlias':
case 'TSInterfaceDeclaration':
case 'TSTypeAliasDeclaration': {
// We do not preserve type annotations/syntax through transformation
return;
}
case 'ClassDeclaration':
case 'DeclareClass':
case 'DeclareExportAllDeclaration':
case 'DeclareExportDeclaration':
@@ -1416,7 +1385,8 @@ function lowerStatement(
case 'TSExportAssignment':
case 'TSImportEqualsDeclaration':
case 'TSModuleDeclaration':
case 'TSNamespaceExportDeclaration': {
case 'TSNamespaceExportDeclaration':
case 'WithStatement': {
builder.errors.push({
reason: `(BuildHIR::lowerStatement) Handle ${stmtPath.type} statements`,
severity: ErrorSeverity.Todo,
@@ -3533,16 +3503,6 @@ function lowerIdentifier(
return place;
}
default: {
if (binding.kind === 'Global' && binding.name === 'eval') {
builder.errors.push({
reason: `The 'eval' function is not supported`,
description:
'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler',
severity: ErrorSeverity.InvalidJS,
loc: exprPath.node.loc ?? null,
suggestions: null,
});
}
return lowerValueToTemporary(builder, {
kind: 'LoadGlobal',
binding,

View File

@@ -279,6 +279,7 @@ export type HIRFunction = {
env: Environment;
params: Array<Place | SpreadPattern>;
returnTypeAnnotation: t.FlowType | t.TSType | null;
returnType: Type;
returns: Place;
context: Array<Place>;
effects: Array<FunctionEffect> | null;

View File

@@ -107,17 +107,6 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
merged.merge(block.id, predecessorId);
fn.body.blocks.delete(block.id);
}
for (const [, block] of fn.body.blocks) {
for (const phi of block.phis) {
for (const [predecessorId, operand] of phi.operands) {
const mapped = merged.get(predecessorId);
if (mapped !== predecessorId) {
phi.operands.delete(predecessorId);
phi.operands.set(mapped, operand);
}
}
}
}
markPredecessors(fn.body);
for (const [, {terminal}] of fn.body.blocks) {
if (terminalHasFallthrough(terminal)) {

View File

@@ -54,8 +54,6 @@ export function printFunction(fn: HIRFunction): string {
let definition = '';
if (fn.id !== null) {
definition += fn.id;
} else {
definition += '<<anonymous>>';
}
if (fn.params.length !== 0) {
definition +=
@@ -73,8 +71,10 @@ export function printFunction(fn: HIRFunction): string {
} else {
definition += '()';
}
definition += `: ${printPlace(fn.returns)}`;
output.push(definition);
if (definition.length !== 0) {
output.push(definition);
}
output.push(`: ${printType(fn.returnType)} @ ${printPlace(fn.returns)}`);
output.push(...fn.directives);
output.push(printHIR(fn.body));
return output.join('\n');
@@ -715,7 +715,7 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
break;
}
case 'FinishMemoize': {
value = `FinishMemoize decl=${printPlace(instrValue.decl)}${instrValue.pruned ? ' pruned' : ''}`;
value = `FinishMemoize decl=${printPlace(instrValue.decl)}`;
break;
}
default: {

View File

@@ -18,7 +18,6 @@ import {
ValueKind,
ValueReason,
Place,
isPrimitiveType,
} from '../HIR/HIR';
import {
eachInstructionLValue,
@@ -472,15 +471,15 @@ export function inferMutationAliasingRanges(
* Here we populate an effect to create the return value as well as populating alias/capture
* effects for how data flows between the params, context vars, and return.
*/
const returns = fn.returns.identifier;
functionEffects.push({
kind: 'Create',
into: fn.returns,
value: isPrimitiveType(returns)
? ValueKind.Primitive
: isJsxType(returns.type)
? ValueKind.Frozen
: ValueKind.Mutable,
value:
fn.returnType.kind === 'Primitive'
? ValueKind.Primitive
: isJsxType(fn.returnType)
? ValueKind.Frozen
: ValueKind.Mutable,
reason: ValueReason.KnownReturnSignature,
});
/**

View File

@@ -11,7 +11,6 @@ import {
Environment,
FunctionExpression,
GeneratedSource,
GotoTerminal,
GotoVariant,
HIRFunction,
IdentifierId,
@@ -20,7 +19,6 @@ import {
Place,
isStatementBlockKind,
makeInstructionId,
mergeConsecutiveBlocks,
promoteTemporary,
reversePostorderBlocks,
} from '../HIR';
@@ -75,10 +73,6 @@ import {retainWhere} from '../Utils/utils';
* - All return statements in the original function expression are replaced with a
* StoreLocal to the temporary we allocated before plus a Goto to the fallthrough
* block (code following the CallExpression).
*
* Note that if the inliined function has only one return, we avoid the labeled block
* and fully inline the code. The original return is replaced with an assignmen to the
* IIFE's call expression lvalue.
*/
export function inlineImmediatelyInvokedFunctionExpressions(
fn: HIRFunction,
@@ -152,75 +146,37 @@ export function inlineImmediatelyInvokedFunctionExpressions(
*/
block.instructions.length = ii;
if (hasSingleExitReturnTerminal(body.loweredFunc.func)) {
block.terminal = {
kind: 'goto',
block: body.loweredFunc.func.body.entry,
id: block.terminal.id,
loc: block.terminal.loc,
variant: GotoVariant.Break,
} as GotoTerminal;
for (const block of body.loweredFunc.func.body.blocks.values()) {
if (block.terminal.kind === 'return') {
block.instructions.push({
id: makeInstructionId(0),
loc: block.terminal.loc,
lvalue: instr.lvalue,
value: {
kind: 'LoadLocal',
loc: block.terminal.loc,
place: block.terminal.value,
},
effects: null,
});
block.terminal = {
kind: 'goto',
block: continuationBlockId,
id: block.terminal.id,
loc: block.terminal.loc,
variant: GotoVariant.Break,
} as GotoTerminal;
}
}
for (const [id, block] of body.loweredFunc.func.body.blocks) {
block.preds.clear();
fn.body.blocks.set(id, block);
}
} else {
/*
* To account for multiple returns within the lambda, we treat the lambda
* as if it were a single labeled statement, and replace all returns with gotos
* to the label fallthrough.
*/
const newTerminal: LabelTerminal = {
block: body.loweredFunc.func.body.entry,
id: makeInstructionId(0),
kind: 'label',
fallthrough: continuationBlockId,
loc: block.terminal.loc,
};
block.terminal = newTerminal;
/*
* To account for complex control flow within the lambda, we treat the lambda
* as if it were a single labeled statement, and replace all returns with gotos
* to the label fallthrough.
*/
const newTerminal: LabelTerminal = {
block: body.loweredFunc.func.body.entry,
id: makeInstructionId(0),
kind: 'label',
fallthrough: continuationBlockId,
loc: block.terminal.loc,
};
block.terminal = newTerminal;
// We store the result in the IIFE temporary
const result = instr.lvalue;
// We store the result in the IIFE temporary
const result = instr.lvalue;
// Declare the IIFE temporary
declareTemporary(fn.env, block, result);
// Declare the IIFE temporary
declareTemporary(fn.env, block, result);
// Promote the temporary with a name as we require this to persist
if (result.identifier.name == null) {
promoteTemporary(result.identifier);
}
// Promote the temporary with a name as we require this to persist
promoteTemporary(result.identifier);
/*
* Rewrite blocks from the lambda to replace any `return` with a
* store to the result and `goto` the continuation block
*/
for (const [id, block] of body.loweredFunc.func.body.blocks) {
block.preds.clear();
rewriteBlock(fn.env, block, continuationBlockId, result);
fn.body.blocks.set(id, block);
}
/*
* Rewrite blocks from the lambda to replace any `return` with a
* store to the result and `goto` the continuation block
*/
for (const [id, block] of body.loweredFunc.func.body.blocks) {
block.preds.clear();
rewriteBlock(fn.env, block, continuationBlockId, result);
fn.body.blocks.set(id, block);
}
/*
@@ -243,7 +199,7 @@ export function inlineImmediatelyInvokedFunctionExpressions(
if (inlinedFunctions.size !== 0) {
// Remove instructions that define lambdas which we inlined
for (const block of fn.body.blocks.values()) {
for (const [, block] of fn.body.blocks) {
retainWhere(
block.instructions,
instr => !inlinedFunctions.has(instr.lvalue.identifier.id),
@@ -257,25 +213,9 @@ export function inlineImmediatelyInvokedFunctionExpressions(
reversePostorderBlocks(fn.body);
markInstructionIds(fn.body);
markPredecessors(fn.body);
mergeConsecutiveBlocks(fn);
}
}
/**
* Returns true if the function has a single exit terminal (throw/return) which is a return
*/
function hasSingleExitReturnTerminal(fn: HIRFunction): boolean {
let hasReturn = false;
let exitCount = 0;
for (const [, block] of fn.body.blocks) {
if (block.terminal.kind === 'return' || block.terminal.kind === 'throw') {
hasReturn ||= block.terminal.kind === 'return';
exitCount++;
}
}
return exitCount === 1 && hasReturn;
}
/*
* Rewrites the block so that all `return` terminals are replaced:
* * Add a StoreLocal <returnValue> = <terminal.value>

View File

@@ -25,6 +25,7 @@ import {
makeBlockId,
makeInstructionId,
makePropertyLiteral,
makeType,
markInstructionIds,
promoteTemporary,
reversePostorderBlocks,
@@ -252,6 +253,7 @@ function emitSelectorFn(env: Environment, keys: Array<string>): Instruction {
env,
params: [obj],
returnTypeAnnotation: null,
returnType: makeType(),
returns: createTemporaryPlace(env, GeneratedSource),
context: [],
effects: null,

View File

@@ -21,6 +21,7 @@ import {
makeBlockId,
makeIdentifierName,
makeInstructionId,
makeType,
ObjectProperty,
Place,
promoteTemporary,
@@ -367,6 +368,7 @@ function emitOutlinedFn(
env,
params: [propsObj],
returnTypeAnnotation: null,
returnType: makeType(),
returns: createTemporaryPlace(env, GeneratedSource),
context: [],
effects: null,

View File

@@ -349,9 +349,11 @@ function codegenReactiveFunction(
fn: ReactiveFunction,
): Result<CodegenFunction, CompilerError> {
for (const param of fn.params) {
const place = param.kind === 'Identifier' ? param : param.place;
cx.temp.set(place.identifier.declarationId, null);
cx.declare(place.identifier);
if (param.kind === 'Identifier') {
cx.temp.set(param.identifier.declarationId, null);
} else {
cx.temp.set(param.place.identifier.declarationId, null);
}
}
const params = fn.params.map(param => convertParameter(param));
@@ -1181,7 +1183,7 @@ function codegenTerminal(
? codegenPlaceToExpression(cx, case_.test)
: null;
const block = codegenBlock(cx, case_.block!);
return t.switchCase(test, block.body.length === 0 ? [] : [block]);
return t.switchCase(test, [block]);
}),
);
}

View File

@@ -79,10 +79,6 @@ export function extractScopeDeclarationsFromDestructuring(
fn: ReactiveFunction,
): void {
const state = new State(fn.env);
for (const param of fn.params) {
const place = param.kind === 'Identifier' ? param : param.place;
state.declared.add(place.identifier.declarationId);
}
visitReactiveFunction(fn, new Visitor(), state);
}

View File

@@ -1064,29 +1064,12 @@ class PruneScopesTransform extends ReactiveFunctionTransform<
const value = instruction.value;
if (value.kind === 'StoreLocal' && value.lvalue.kind === 'Reassign') {
// Complex cases of useMemo inlining result in a temporary that is reassigned
const ids = getOrInsertDefault(
this.reassignments,
value.lvalue.place.identifier.declarationId,
new Set(),
);
ids.add(value.value.identifier);
} else if (
value.kind === 'LoadLocal' &&
value.place.identifier.scope != null &&
instruction.lvalue != null &&
instruction.lvalue.identifier.scope == null
) {
/*
* Simpler cases result in a direct assignment to the original lvalue, with a
* LoadLocal
*/
const ids = getOrInsertDefault(
this.reassignments,
instruction.lvalue.identifier.declarationId,
new Set(),
);
ids.add(value.place.identifier);
} else if (value.kind === 'FinishMemoize') {
let decls;
if (value.decl.identifier.scope == null) {

View File

@@ -90,8 +90,7 @@ function apply(func: HIRFunction, unifier: Unifier): void {
}
}
}
const returns = func.returns.identifier;
returns.type = unifier.get(returns.type);
func.returnType = unifier.get(func.returnType);
}
type TypeEquation = {
@@ -144,12 +143,12 @@ function* generate(
}
}
if (returnTypes.length > 1) {
yield equation(func.returns.identifier.type, {
yield equation(func.returnType, {
kind: 'Phi',
operands: returnTypes,
});
} else if (returnTypes.length === 1) {
yield equation(func.returns.identifier.type, returnTypes[0]!);
yield equation(func.returnType, returnTypes[0]!);
}
}
@@ -408,7 +407,7 @@ function* generateInstructionTypes(
yield equation(left, {
kind: 'Function',
shapeId: BuiltInFunctionId,
return: value.loweredFunc.func.returns.identifier.type,
return: value.loweredFunc.func.returnType,
isConstructor: false,
});
break;

View File

@@ -445,13 +445,11 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
*/
this.recordTemporaries(instruction, state);
const value = instruction.value;
// Track reassignments from inlining of manual memo
if (
value.kind === 'StoreLocal' &&
value.lvalue.kind === 'Reassign' &&
state.manualMemoState != null
) {
// Complex cases of inlining end up with a temporary that is reassigned
const ids = getOrInsertDefault(
state.manualMemoState.reassignments,
value.lvalue.place.identifier.declarationId,
@@ -459,21 +457,6 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
);
ids.add(value.value.identifier);
}
if (
value.kind === 'LoadLocal' &&
value.place.identifier.scope != null &&
instruction.lvalue != null &&
instruction.lvalue.identifier.scope == null &&
state.manualMemoState != null
) {
// Simpler cases of inlining assign to the original IIFE lvalue
const ids = getOrInsertDefault(
state.manualMemoState.reassignments,
instruction.lvalue.identifier.declarationId,
new Set(),
);
ids.add(value.place.identifier);
}
if (value.kind === 'StartMemoize') {
let depsFromSource: Array<ManualMemoDependency> | null = null;
if (value.deps != null) {

View File

@@ -26,16 +26,20 @@ import { c as _c } from "react/compiler-runtime";
import { getNull } from "shared-runtime";
function Component(props) {
const $ = _c(2);
const $ = _c(3);
let t0;
let items;
if ($[0] !== props.a) {
items = getNull() ?? [];
t0 = getNull() ?? [];
items = t0;
items.push(props.a);
$[0] = props.a;
$[1] = items;
$[2] = t0;
} else {
items = $[1];
t0 = $[2];
}
return items;
}

View File

@@ -52,13 +52,15 @@ function Component(t0) {
}
const onClick = t1;
let t2;
let t3;
if ($[2] !== onClick) {
t2 = <div onClick={onClick}>{someGlobal.value}</div>;
t3 = <div onClick={onClick}>{someGlobal.value}</div>;
$[2] = onClick;
$[3] = t2;
$[3] = t3;
} else {
t2 = $[3];
t3 = $[3];
}
t2 = t3;
return t2;
}

View File

@@ -30,46 +30,50 @@ function Component(props) {
const $ = _c(4);
const [x] = useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[2] !== expensiveNumber) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t2 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
function Component2(props) {
const $ = _c(4);
const [x] = useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[2] !== expensiveNumber) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t2 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
```

View File

@@ -32,46 +32,50 @@ function Component(props) {
const $ = _c(4);
const [x] = useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[2] !== expensiveNumber) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t2 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
function Component2(props) {
const $ = _c(4);
const [x] = useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[2] !== expensiveNumber) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t2 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
```

View File

@@ -30,23 +30,25 @@ function Component(props) {
const $ = _c(4);
const [x] = React.useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[2] !== expensiveNumber) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t2 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -36,28 +36,30 @@ function Component(props) {
const $ = _c(4);
const [x] = React.useState(0);
let t0;
if ($[0] !== x) {
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t0;
} else {
t0 = $[1];
}
const expensiveNumber = t0;
let t1;
if ($[0] !== x) {
t1 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
} else {
t1 = $[1];
}
t0 = t1;
const expensiveNumber = t0;
let t2;
if ($[2] !== expensiveNumber) {
t1 = (
t2 = (
<div>
{expensiveNumber}
{`${someImport}`}
</div>
);
$[2] = expensiveNumber;
$[3] = t1;
$[3] = t2;
} else {
t1 = $[3];
t2 = $[3];
}
return t1;
return t2;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -36,22 +36,26 @@ import { useMemo } from "react";
function Component(props) {
const $ = _c(2);
let t0;
let t1;
if ($[0] !== props.value) {
t0 = { value: props.value };
t1 = { value: props.value };
$[0] = props.value;
$[1] = t0;
$[1] = t1;
} else {
t0 = $[1];
t1 = $[1];
}
const handlers = t0;
const handlers = t1;
bb0: switch (props.test) {
case true: {
console.log(handlers.value);
break bb0;
}
default:
default: {
}
}
const outerHandlers = handlers;
t0 = handlers;
const outerHandlers = t0;
return outerHandlers;
}

View File

@@ -37,9 +37,11 @@ function useTest() {
const t1 = (w = 42);
const t2 = w;
let t3;
w = 999;
t0 = makeArray(t1, t2, 2);
t3 = 2;
t0 = makeArray(t1, t2, t3);
$[0] = t0;
} else {
t0 = $[0];

View File

@@ -37,9 +37,11 @@ function useTest() {
const t1 = (w.x = 42);
const t2 = w.x;
let t3;
w.x = 999;
t0 = makeArray(t1, t2, 2);
t3 = 2;
t0 = makeArray(t1, t2, t3);
$[0] = t0;
} else {
t0 = $[0];

View File

@@ -32,9 +32,11 @@ function useTest() {
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const t1 = print(1);
let t2;
print(2);
t0 = makeArray(t1, 2);
t2 = 2;
t0 = makeArray(t1, t2);
$[0] = t0;
} else {
t0 = $[0];

View File

@@ -29,33 +29,37 @@ function useHook(t0) {
const $ = _c(7);
const { a, b } = t0;
let t1;
if ($[0] !== a) {
t1 = identity({ a });
$[0] = a;
$[1] = t1;
} else {
t1 = $[1];
}
const valA = t1;
let t2;
if ($[2] !== b) {
t2 = identity([b]);
$[2] = b;
$[3] = t2;
if ($[0] !== a) {
t2 = identity({ a });
$[0] = a;
$[1] = t2;
} else {
t2 = $[3];
t2 = $[1];
}
const valB = t2;
t1 = t2;
const valA = t1;
let t3;
let t4;
if ($[2] !== b) {
t4 = identity([b]);
$[2] = b;
$[3] = t4;
} else {
t4 = $[3];
}
t3 = t4;
const valB = t3;
let t5;
if ($[4] !== valA || $[5] !== valB) {
t3 = [valA, valB];
t5 = [valA, valB];
$[4] = valA;
$[5] = valB;
$[6] = t3;
$[6] = t5;
} else {
t3 = $[6];
t5 = $[6];
}
return t3;
return t5;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -34,8 +34,10 @@ function Component(props) {
let Component;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
Component = Stringify;
let t0;
Component = Component;
t0 = Component;
Component = t0;
$[0] = Component;
} else {
Component = $[0];

View File

@@ -28,18 +28,20 @@ import { c as _c } from "react/compiler-runtime";
function Foo() {
const $ = _c(1);
let t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = function a(t1) {
const x_0 = t1 === undefined ? _temp : t1;
return (function b(t2) {
const y_0 = t2 === undefined ? [] : t2;
t1 = function a(t2) {
const x_0 = t2 === undefined ? _temp : t2;
return (function b(t3) {
const y_0 = t3 === undefined ? [] : t3;
return [x_0, y_0];
})();
};
$[0] = t0;
$[0] = t1;
} else {
t0 = $[0];
t1 = $[0];
}
t0 = t1;
return t0;
}
function _temp() {}

View File

@@ -67,7 +67,8 @@ function Component(props) {
case "b": {
break bb1;
}
case "c":
case "c": {
}
default: {
x = 6;
}

View File

@@ -28,6 +28,7 @@ import * as React from "react";
function Component(props) {
const $ = _c(2);
let t0;
let x;
if ($[0] !== props.value) {
x = [];
@@ -37,7 +38,8 @@ function Component(props) {
} else {
x = $[1];
}
const x_0 = x;
t0 = x;
const x_0 = t0;
return x_0;
}

View File

@@ -1,24 +0,0 @@
## Input
```javascript
function Component(props) {
eval('props.x = true');
return <div />;
}
```
## Error
```
1 | function Component(props) {
> 2 | eval('props.x = true');
| ^^^^ InvalidJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
3 | return <div />;
4 | }
5 |
```

View File

@@ -1,4 +0,0 @@
function Component(props) {
eval('props.x = true');
return <div />;
}

View File

@@ -84,7 +84,7 @@ let moduleLocal = false;
> 3 | var x = [];
| ^^^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
Todo: Support nested class declarations (5:10)
Todo: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10)
Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)

View File

@@ -42,32 +42,34 @@ function Component(props) {
const c1 = __c;
const $c = c1;
let t0;
if ($[0] !== $c) {
t0 = [$c];
$[0] = $c;
$[1] = t0;
} else {
t0 = $[1];
}
const array = t0;
let t1;
if ($[2] !== state) {
t1 = [state];
$[2] = state;
$[3] = t1;
if ($[0] !== $c) {
t1 = [$c];
$[0] = $c;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
t0 = t1;
const array = t0;
let t2;
if ($[4] !== array || $[5] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={array} />;
$[4] = array;
$[5] = t1;
$[6] = t2;
if ($[2] !== state) {
t2 = [state];
$[2] = state;
$[3] = t2;
} else {
t2 = $[6];
t2 = $[3];
}
return t2;
let t3;
if ($[4] !== array || $[5] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={array} />;
$[4] = array;
$[5] = t2;
$[6] = t3;
} else {
t3 = $[6];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -63,21 +63,23 @@ function Component() {
unsafeUpdateConst();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [{ pretendConst }];
$[0] = t0;
} else {
t0 = $[0];
}
const value = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <ValidateMemoization inputs={[]} output={value} />;
$[1] = t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = [{ pretendConst }];
$[0] = t1;
} else {
t1 = $[1];
t1 = $[0];
}
return t1;
t0 = t1;
const value = t0;
let t2;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <ValidateMemoization inputs={[]} output={value} />;
$[1] = t2;
} else {
t2 = $[1];
}
return t2;
}
function _temp() {
unsafeResetConst();

View File

@@ -74,21 +74,23 @@ function Component() {
unsafeUpdateConst();
let t0;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [{ pretendConst }];
$[1] = t0;
} else {
t0 = $[1];
}
const value = t0;
let t1;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <ValidateMemoization inputs={[pretendConst]} output={value} />;
$[2] = t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = [{ pretendConst }];
$[1] = t1;
} else {
t1 = $[2];
t1 = $[1];
}
return t1;
t0 = t1;
const value = t0;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <ValidateMemoization inputs={[pretendConst]} output={value} />;
$[2] = t2;
} else {
t2 = $[2];
}
return t2;
}
function _temp() {
unsafeResetConst();

View File

@@ -38,34 +38,36 @@ function Component(props) {
$[0] = "20945b0193e529df490847c66111b38d7b02485d5b53d0829ff3b23af87b105c";
}
const [state] = useState(0);
const t0 = state * 2;
let t1;
if ($[1] !== t0) {
t1 = [t0];
$[1] = t0;
$[2] = t1;
} else {
t1 = $[2];
}
const doubled = t1;
let t0;
const t1 = state * 2;
let t2;
if ($[3] !== state) {
t2 = [state];
$[3] = state;
$[4] = t2;
if ($[1] !== t1) {
t2 = [t1];
$[1] = t1;
$[2] = t2;
} else {
t2 = $[4];
t2 = $[2];
}
t0 = t2;
const doubled = t0;
let t3;
if ($[5] !== doubled || $[6] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={doubled} />;
$[5] = doubled;
$[6] = t2;
$[7] = t3;
if ($[3] !== state) {
t3 = [state];
$[3] = state;
$[4] = t3;
} else {
t3 = $[7];
t3 = $[4];
}
return t3;
let t4;
if ($[5] !== doubled || $[6] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={doubled} />;
$[5] = doubled;
$[6] = t3;
$[7] = t4;
} else {
t4 = $[7];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -40,34 +40,36 @@ function Component(t0) {
const $ = _c(7);
const { data } = t0;
let t1;
let t2;
if ($[0] !== data.name) {
t1 = fbt._("{name}", [fbt._param("name", data.name ?? "")], {
t2 = fbt._("{name}", [fbt._param("name", data.name ?? "")], {
hk: "csQUH",
});
$[0] = data.name;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const el = t1;
let t2;
if ($[2] !== data.name) {
t2 = [data.name];
$[2] = data.name;
$[3] = t2;
} else {
t2 = $[3];
}
let t3;
if ($[4] !== el || $[5] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={el} />;
$[4] = el;
$[5] = t2;
$[6] = t3;
if ($[2] !== data.name) {
t3 = [data.name];
$[2] = data.name;
$[3] = t3;
} else {
t3 = $[6];
t3 = $[3];
}
return t3;
let t4;
if ($[4] !== el || $[5] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={el} />;
$[4] = el;
$[5] = t3;
$[6] = t4;
} else {
t4 = $[6];
}
return t4;
}
const props1 = { data: { name: "Mike" } };

View File

@@ -47,14 +47,17 @@ function Component(t0) {
const $ = _c(19);
const { a, b } = t0;
let t1;
let t2;
if ($[0] !== a) {
t1 = [a];
t2 = [a];
$[0] = a;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const x = t1;
let t3;
let items;
if ($[2] !== b || $[3] !== x) {
items = [b];
@@ -67,57 +70,59 @@ function Component(t0) {
} else {
items = $[4];
}
const y = items;
let t2;
if ($[5] !== a) {
t2 = [a];
$[5] = a;
$[6] = t2;
} else {
t2 = $[6];
}
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
t3 = items;
const y = t3;
let t4;
if ($[10] !== b || $[11] !== x) {
t4 = [x, b];
$[10] = b;
$[11] = x;
$[12] = t4;
if ($[5] !== a) {
t4 = [a];
$[5] = a;
$[6] = t4;
} else {
t4 = $[12];
t4 = $[6];
}
let t5;
if ($[13] !== t4 || $[14] !== y) {
t5 = <ValidateMemoization inputs={t4} output={y} />;
$[13] = t4;
$[14] = y;
$[15] = t5;
if ($[7] !== t4 || $[8] !== x) {
t5 = <ValidateMemoization inputs={t4} output={x} />;
$[7] = t4;
$[8] = x;
$[9] = t5;
} else {
t5 = $[15];
t5 = $[9];
}
let t6;
if ($[16] !== t3 || $[17] !== t5) {
t6 = (
if ($[10] !== b || $[11] !== x) {
t6 = [x, b];
$[10] = b;
$[11] = x;
$[12] = t6;
} else {
t6 = $[12];
}
let t7;
if ($[13] !== t6 || $[14] !== y) {
t7 = <ValidateMemoization inputs={t6} output={y} />;
$[13] = t6;
$[14] = y;
$[15] = t7;
} else {
t7 = $[15];
}
let t8;
if ($[16] !== t5 || $[17] !== t7) {
t8 = (
<>
{t3}
{t5}
{t7}
</>
);
$[16] = t3;
$[17] = t5;
$[18] = t6;
$[16] = t5;
$[17] = t7;
$[18] = t8;
} else {
t6 = $[18];
t8 = $[18];
}
return t6;
return t8;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -34,6 +34,7 @@ import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(7);
let t0;
let a;
if ($[0] !== props.name) {
a = [];
@@ -47,25 +48,26 @@ function Component(props) {
} else {
a = $[1];
}
const a_0 = a;
let t0;
if ($[2] !== props.name) {
t0 = [props.name];
$[2] = props.name;
$[3] = t0;
} else {
t0 = $[3];
}
t0 = a;
const a_0 = t0;
let t1;
if ($[4] !== a_0 || $[5] !== t0) {
t1 = <ValidateMemoization inputs={t0} output={a_0} />;
$[4] = a_0;
$[5] = t0;
$[6] = t1;
if ($[2] !== props.name) {
t1 = [props.name];
$[2] = props.name;
$[3] = t1;
} else {
t1 = $[6];
t1 = $[3];
}
return t1;
let t2;
if ($[4] !== a_0 || $[5] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={a_0} />;
$[4] = a_0;
$[5] = t1;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -46,7 +46,7 @@ const React$useMemo = React.useMemo;
const Internal$Reassigned$useHook = useHook;
function Component() {
const $ = _c(7);
const $ = _c(8);
const [state] = React$useState(0);
const object = Internal$Reassigned$useHook();
let t0;
@@ -59,30 +59,34 @@ function Component() {
}
const json = t0;
let t1;
if ($[2] !== state) {
const doubledArray = makeArray(state);
t1 = doubledArray.join("");
$[2] = state;
$[3] = t1;
} else {
t1 = $[3];
}
let t2;
if ($[4] !== json || $[5] !== t1) {
t2 = (
if ($[2] !== state) {
t1 = makeArray(state);
const doubledArray = t1;
t2 = doubledArray.join("");
$[2] = state;
$[3] = t2;
$[4] = t1;
} else {
t2 = $[3];
t1 = $[4];
}
let t3;
if ($[5] !== json || $[6] !== t2) {
t3 = (
<div>
{t1}
{t2}
{json}
</div>
);
$[4] = json;
$[5] = t1;
$[5] = json;
$[6] = t2;
$[7] = t3;
} else {
t2 = $[6];
t3 = $[7];
}
return t2;
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -22,16 +22,20 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
import { c as _c } from "react/compiler-runtime";
function Component(props) {
const $ = _c(2);
const $ = _c(3);
let t0;
let items;
if ($[0] !== props.a) {
items = [];
t0 = [];
items = t0;
items.push(props.a);
$[0] = props.a;
$[1] = items;
$[2] = t0;
} else {
items = $[1];
t0 = $[2];
}
return items;
}

View File

@@ -50,17 +50,19 @@ function useMakeCallback(t0) {
const [, setState] = useState(0);
let t1;
let t2;
if ($[0] !== obj.value) {
t1 = () => {
t2 = () => {
if (obj.value !== 0) {
setState(obj.value);
}
};
$[0] = obj.value;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const cb = t1;
useIdentity(null);

View File

@@ -26,15 +26,17 @@ import { c as _c } from "react/compiler-runtime";
function Foo() {
const $ = _c(1);
let t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = function a(t1) {
const x_0 = t1 === undefined ? _temp : t1;
t1 = function a(t2) {
const x_0 = t2 === undefined ? _temp : t2;
return x_0;
};
$[0] = t0;
$[0] = t1;
} else {
t0 = $[0];
t1 = $[0];
}
t0 = t1;
return t0;
}
function _temp() {}

View File

@@ -37,11 +37,13 @@ import { useMemo } from "react";
import { identity, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const $ = _c(10);
const { a, b } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
t1 = { a };
x = t1;
const f = () => identity(x);
const x2 = f();
@@ -49,28 +51,30 @@ function Component(t0) {
$[0] = a;
$[1] = b;
$[2] = x;
$[3] = t1;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
t1 = $[3];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
if ($[4] !== a || $[5] !== b) {
t2 = [a, b];
$[4] = a;
$[5] = b;
$[6] = t2;
} else {
t2 = $[8];
t2 = $[6];
}
return t2;
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -34,38 +34,42 @@ import { useMemo } from "react";
import { identity, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const $ = _c(10);
const { a, b } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
t1 = { a };
x = t1;
const x2 = identity(x);
x2.b = b;
$[0] = a;
$[1] = b;
$[2] = x;
$[3] = t1;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
t1 = $[3];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
if ($[4] !== a || $[5] !== b) {
t2 = [a, b];
$[4] = a;
$[5] = b;
$[6] = t2;
} else {
t2 = $[8];
t2 = $[6];
}
return t2;
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -60,11 +60,13 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(21);
const $ = _c(22);
const { a, b, c } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b || $[2] !== c) {
x = [{ value: a }];
t1 = [{ value: a }];
x = t1;
if (b === 0) {
x.push({ value: c });
} else {
@@ -74,61 +76,63 @@ function Component(t0) {
$[1] = b;
$[2] = c;
$[3] = x;
$[4] = t1;
} else {
x = $[3];
}
let t1;
if ($[4] !== a || $[5] !== b || $[6] !== c) {
t1 = [a, b, c];
$[4] = a;
$[5] = b;
$[6] = c;
$[7] = t1;
} else {
t1 = $[7];
t1 = $[4];
}
let t2;
if ($[8] !== t1 || $[9] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[8] = t1;
$[9] = x;
$[10] = t2;
if ($[5] !== a || $[6] !== b || $[7] !== c) {
t2 = [a, b, c];
$[5] = a;
$[6] = b;
$[7] = c;
$[8] = t2;
} else {
t2 = $[10];
t2 = $[8];
}
let t3;
if ($[11] !== a || $[12] !== b || $[13] !== c) {
t3 = [a, b, c];
$[11] = a;
$[12] = b;
$[13] = c;
$[14] = t3;
if ($[9] !== t2 || $[10] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[9] = t2;
$[10] = x;
$[11] = t3;
} else {
t3 = $[14];
t3 = $[11];
}
let t4;
if ($[15] !== t3 || $[16] !== x[0]) {
t4 = <ValidateMemoization inputs={t3} output={x[0]} />;
$[15] = t3;
$[16] = x[0];
$[17] = t4;
if ($[12] !== a || $[13] !== b || $[14] !== c) {
t4 = [a, b, c];
$[12] = a;
$[13] = b;
$[14] = c;
$[15] = t4;
} else {
t4 = $[17];
t4 = $[15];
}
let t5;
if ($[18] !== t2 || $[19] !== t4) {
t5 = (
if ($[16] !== t4 || $[17] !== x[0]) {
t5 = <ValidateMemoization inputs={t4} output={x[0]} />;
$[16] = t4;
$[17] = x[0];
$[18] = t5;
} else {
t5 = $[18];
}
let t6;
if ($[19] !== t3 || $[20] !== t5) {
t6 = (
<>
{t2};{t4};
{t3};{t5};
</>
);
$[18] = t2;
$[19] = t4;
$[19] = t3;
$[20] = t5;
$[21] = t6;
} else {
t5 = $[20];
t6 = $[21];
}
return t5;
return t6;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -51,11 +51,13 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const $ = _c(10);
const { a, b } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b) {
x = [{ a }];
t1 = [{ a }];
x = t1;
const f = () => {
const y = typedCreateFrom(x);
const z = typedCapture(y);
@@ -68,28 +70,30 @@ function Component(t0) {
$[0] = a;
$[1] = b;
$[2] = x;
$[3] = t1;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
t1 = $[3];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
if ($[4] !== a || $[5] !== b) {
t2 = [a, b];
$[4] = a;
$[5] = b;
$[6] = t2;
} else {
t2 = $[8];
t2 = $[6];
}
return t2;
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -52,20 +52,24 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(19);
const $ = _c(20);
const { a, b } = t0;
let t1;
let t2;
if ($[0] !== a) {
t1 = { a };
t2 = { a };
$[0] = a;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const o = t1;
let t3;
let x;
if ($[2] !== b || $[3] !== o) {
x = [o];
t3 = [o];
x = t3;
const y = typedCapture(x);
const z = typedCapture(y);
x.push(z);
@@ -73,58 +77,60 @@ function Component(t0) {
$[2] = b;
$[3] = o;
$[4] = x;
$[5] = t3;
} else {
x = $[4];
}
let t2;
if ($[5] !== a) {
t2 = [a];
$[5] = a;
$[6] = t2;
} else {
t2 = $[6];
}
let t3;
if ($[7] !== o || $[8] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={o} />;
$[7] = o;
$[8] = t2;
$[9] = t3;
} else {
t3 = $[9];
t3 = $[5];
}
let t4;
if ($[10] !== a || $[11] !== b) {
t4 = [a, b];
$[10] = a;
$[11] = b;
$[12] = t4;
if ($[6] !== a) {
t4 = [a];
$[6] = a;
$[7] = t4;
} else {
t4 = $[12];
t4 = $[7];
}
let t5;
if ($[13] !== t4 || $[14] !== x) {
t5 = <ValidateMemoization inputs={t4} output={x} />;
$[13] = t4;
$[14] = x;
$[15] = t5;
if ($[8] !== o || $[9] !== t4) {
t5 = <ValidateMemoization inputs={t4} output={o} />;
$[8] = o;
$[9] = t4;
$[10] = t5;
} else {
t5 = $[15];
t5 = $[10];
}
let t6;
if ($[16] !== t3 || $[17] !== t5) {
t6 = (
if ($[11] !== a || $[12] !== b) {
t6 = [a, b];
$[11] = a;
$[12] = b;
$[13] = t6;
} else {
t6 = $[13];
}
let t7;
if ($[14] !== t6 || $[15] !== x) {
t7 = <ValidateMemoization inputs={t6} output={x} />;
$[14] = t6;
$[15] = x;
$[16] = t7;
} else {
t7 = $[16];
}
let t8;
if ($[17] !== t5 || $[18] !== t7) {
t8 = (
<>
{t3};{t5};
{t5};{t7};
</>
);
$[16] = t3;
$[17] = t5;
$[18] = t6;
$[18] = t7;
$[19] = t8;
} else {
t6 = $[18];
t8 = $[19];
}
return t6;
return t8;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -50,11 +50,13 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const $ = _c(10);
const { a, b } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
t1 = { a };
x = t1;
const f = () => {
const y = typedCapture(x);
const z = typedCreateFrom(y);
@@ -67,28 +69,30 @@ function Component(t0) {
$[0] = a;
$[1] = b;
$[2] = x;
$[3] = t1;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
t1 = $[3];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
if ($[4] !== a || $[5] !== b) {
t2 = [a, b];
$[4] = a;
$[5] = b;
$[6] = t2;
} else {
t2 = $[8];
t2 = $[6];
}
return t2;
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -46,11 +46,13 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const $ = _c(10);
const { a, b } = t0;
let t1;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
t1 = { a };
x = t1;
const y = typedCapture(x);
const z = typedCreateFrom(y);
@@ -58,28 +60,30 @@ function Component(t0) {
$[0] = a;
$[1] = b;
$[2] = x;
$[3] = t1;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
t1 = $[3];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
if ($[4] !== a || $[5] !== b) {
t2 = [a, b];
$[4] = a;
$[5] = b;
$[6] = t2;
} else {
t2 = $[8];
t2 = $[6];
}
return t2;
let t3;
if ($[7] !== t2 || $[8] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[7] = t2;
$[8] = x;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -49,36 +49,38 @@ function Component(t0) {
const $ = _c(7);
const { a, b } = t0;
let t1;
let t2;
if ($[0] !== a) {
t1 = [{ a }];
t2 = [{ a }];
$[0] = a;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const x = t1;
const y = typedCreateFrom(x);
const z = typedCapture(y);
typedMutate(z, b);
let t2;
if ($[2] !== a) {
t2 = [a];
$[2] = a;
$[3] = t2;
} else {
t2 = $[3];
}
let t3;
if ($[4] !== t2 || $[5] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[4] = t2;
$[5] = x;
$[6] = t3;
if ($[2] !== a) {
t3 = [a];
$[2] = a;
$[3] = t3;
} else {
t3 = $[6];
t3 = $[3];
}
return t3;
let t4;
if ($[4] !== t3 || $[5] !== x) {
t4 = <ValidateMemoization inputs={t3} output={x} />;
$[4] = t3;
$[5] = x;
$[6] = t4;
} else {
t4 = $[6];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -50,19 +50,21 @@ import {
} from "shared-runtime";
function Component(t0) {
const $ = _c(11);
const $ = _c(12);
const { a, b } = t0;
let t1;
let t2;
if ($[0] !== a) {
t1 = { a };
t2 = { a };
$[0] = a;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
let x;
if ($[2] !== b || $[3] !== t1) {
x = [t1];
if ($[2] !== b || $[3] !== t2) {
t1 = [t2];
x = t1;
let z;
if (b) {
z = x;
@@ -72,30 +74,32 @@ function Component(t0) {
typedMutate(z, b);
$[2] = b;
$[3] = t1;
$[3] = t2;
$[4] = x;
$[5] = t1;
} else {
x = $[4];
}
let t2;
if ($[5] !== a || $[6] !== b) {
t2 = [a, b];
$[5] = a;
$[6] = b;
$[7] = t2;
} else {
t2 = $[7];
t1 = $[5];
}
let t3;
if ($[8] !== t2 || $[9] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[8] = t2;
$[9] = x;
$[10] = t3;
if ($[6] !== a || $[7] !== b) {
t3 = [a, b];
$[6] = a;
$[7] = b;
$[8] = t3;
} else {
t3 = $[10];
t3 = $[8];
}
return t3;
let t4;
if ($[9] !== t3 || $[10] !== x) {
t4 = <ValidateMemoization inputs={t3} output={x} />;
$[9] = t3;
$[10] = x;
$[11] = t4;
} else {
t4 = $[11];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -63,13 +63,15 @@ function Component(t0) {
const $ = _c(7);
const { a, b } = t0;
let t1;
let t2;
if ($[0] !== a) {
t1 = makeObject_Primitives(a);
t2 = makeObject_Primitives(a);
$[0] = a;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const x = t1;
useIdentity(x);
@@ -77,24 +79,24 @@ function Component(t0) {
const x2 = typedIdentity(x);
identity(x2, b);
let t2;
if ($[2] !== a) {
t2 = [a];
$[2] = a;
$[3] = t2;
} else {
t2 = $[3];
}
let t3;
if ($[4] !== t2 || $[5] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[4] = t2;
$[5] = x;
$[6] = t3;
if ($[2] !== a) {
t3 = [a];
$[2] = a;
$[3] = t3;
} else {
t3 = $[6];
t3 = $[3];
}
return t3;
let t4;
if ($[4] !== t3 || $[5] !== x) {
t4 = <ValidateMemoization inputs={t3} output={x} />;
$[4] = t3;
$[5] = x;
$[6] = t4;
} else {
t4 = $[6];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -51,13 +51,15 @@ function useFoo(arr1, arr2) {
y = $[4];
}
let t1;
let t2;
if ($[5] !== y) {
t1 = { y };
t2 = { y };
$[5] = y;
$[6] = t1;
$[6] = t2;
} else {
t1 = $[6];
t2 = $[6];
}
t1 = t2;
return t1;
}

View File

@@ -42,34 +42,36 @@ function Component(t0) {
arg?.items.edges?.nodes;
let t1;
let t2;
if ($[0] !== arg?.items.edges?.nodes) {
t1 = arg?.items.edges?.nodes.map(identity);
t2 = arg?.items.edges?.nodes.map(identity);
$[0] = arg?.items.edges?.nodes;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const data = t1;
const t2 = arg?.items.edges?.nodes;
let t3;
if ($[2] !== t2) {
t3 = [t2];
$[2] = t2;
$[3] = t3;
} else {
t3 = $[3];
}
const t3 = arg?.items.edges?.nodes;
let t4;
if ($[4] !== data || $[5] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={data} />;
$[4] = data;
$[5] = t3;
$[6] = t4;
if ($[2] !== t3) {
t4 = [t3];
$[2] = t3;
$[3] = t4;
} else {
t4 = $[6];
t4 = $[3];
}
return t4;
let t5;
if ($[4] !== data || $[5] !== t4) {
t5 = <ValidateMemoization inputs={t4} output={data} />;
$[4] = data;
$[5] = t4;
$[6] = t5;
} else {
t5 = $[6];
}
return t5;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -23,19 +23,21 @@ import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMe
import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(2);
let t0;
const x$0 = [];
x$0.push(props?.a.b?.c.d?.e);
x$0.push(props.a?.b.c?.d.e);
let t0;
t0 = x$0;
let t1;
if ($[0] !== props.a.b.c.d.e) {
t0 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;
t1 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;
$[0] = props.a.b.c.d.e;
$[1] = t0;
$[1] = t1;
} else {
t0 = $[1];
t1 = $[1];
}
return t0;
return t1;
}
```

View File

@@ -23,6 +23,7 @@ import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMe
import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(7);
let t0;
let x;
if ($[0] !== props.items) {
x = [];
@@ -33,25 +34,26 @@ function Component(props) {
} else {
x = $[1];
}
const data = x;
let t0;
if ($[2] !== props.items) {
t0 = [props.items];
$[2] = props.items;
$[3] = t0;
} else {
t0 = $[3];
}
t0 = x;
const data = t0;
let t1;
if ($[4] !== data || $[5] !== t0) {
t1 = <ValidateMemoization inputs={t0} output={data} />;
$[4] = data;
$[5] = t0;
$[6] = t1;
if ($[2] !== props.items) {
t1 = [props.items];
$[2] = props.items;
$[3] = t1;
} else {
t1 = $[6];
t1 = $[3];
}
return t1;
let t2;
if ($[4] !== data || $[5] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={data} />;
$[4] = data;
$[5] = t1;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
```

View File

@@ -38,6 +38,7 @@ function Component(t0) {
const { arg } = t0;
arg?.items;
let t1;
let x;
if ($[0] !== arg?.items) {
x = [];
@@ -47,26 +48,27 @@ function Component(t0) {
} else {
x = $[1];
}
const data = x;
const t1 = arg?.items;
let t2;
if ($[2] !== t1) {
t2 = [t1];
$[2] = t1;
$[3] = t2;
} else {
t2 = $[3];
}
t1 = x;
const data = t1;
const t2 = arg?.items;
let t3;
if ($[4] !== data || $[5] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={data} />;
$[4] = data;
$[5] = t2;
$[6] = t3;
if ($[2] !== t2) {
t3 = [t2];
$[2] = t2;
$[3] = t3;
} else {
t3 = $[6];
t3 = $[3];
}
return t3;
let t4;
if ($[4] !== data || $[5] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={data} />;
$[4] = data;
$[5] = t3;
$[6] = t4;
} else {
t4 = $[6];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -36,9 +36,11 @@ import { useMemo } from "react";
// (i.e. inferred non-mutable or non-escaping values don't get memoized)
function useFoo(t0) {
const { minWidth, styles, setStyles } = t0;
let t1;
if (styles.width > minWidth) {
setStyles(styles);
}
t1 = undefined;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -34,7 +34,10 @@ import { identity } from "shared-runtime";
* This is technically a false positive, although it makes sense
* to bailout as source code might be doing something sketchy.
*/
function useFoo(x) {}
function useFoo(x) {
let t0;
t0 = identity(x);
}
export const FIXTURE_ENTRYPOINT = {
fn: useFoo,

View File

@@ -40,12 +40,14 @@ function useFoo() {
const $ = _c(1);
const constVal = 0;
let t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [0];
$[0] = t0;
t1 = [0];
$[0] = t1;
} else {
t0 = $[0];
t1 = $[0];
}
t0 = t1;
return t0;
}

View File

@@ -32,14 +32,16 @@ function Component(t0) {
const { propA, propB } = t0;
const x = propB.x.y;
let t1;
let t2;
if ($[0] !== propA.x || $[1] !== x) {
t1 = sum(propA.x, x);
t2 = sum(propA.x, x);
$[0] = propA.x;
$[1] = x;
$[2] = t1;
$[2] = t2;
} else {
t1 = $[2];
t2 = $[2];
}
t1 = t2;
return t1;
}

View File

@@ -32,26 +32,28 @@ import { identity } from "shared-runtime";
function Component(t0) {
const $ = _c(5);
const { propA, propB } = t0;
let t1;
const t1 = propB?.x.y;
let t2;
if ($[0] !== t1) {
t2 = identity(t1);
$[0] = t1;
$[1] = t2;
} else {
t2 = $[1];
}
const t2 = propB?.x.y;
let t3;
if ($[2] !== propA || $[3] !== t2) {
t3 = { value: t2, other: propA };
$[2] = propA;
$[3] = t2;
$[4] = t3;
if ($[0] !== t2) {
t3 = identity(t2);
$[0] = t2;
$[1] = t3;
} else {
t3 = $[4];
t3 = $[1];
}
return t3;
let t4;
if ($[2] !== propA || $[3] !== t3) {
t4 = { value: t3, other: propA };
$[2] = propA;
$[3] = t3;
$[4] = t4;
} else {
t4 = $[4];
}
t1 = t4;
return t1;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -30,18 +30,20 @@ import { useMemo } from "react";
function Component(t0) {
const $ = _c(3);
const { propA, propB } = t0;
let t1;
const t1 = propB?.x.y;
let t2;
if ($[0] !== propA || $[1] !== t1) {
t2 = { value: t1, other: propA };
const t2 = propB?.x.y;
let t3;
if ($[0] !== propA || $[1] !== t2) {
t3 = { value: t2, other: propA };
$[0] = propA;
$[1] = t1;
$[2] = t2;
$[1] = t2;
$[2] = t3;
} else {
t2 = $[2];
t3 = $[2];
}
return t2;
t1 = t3;
return t1;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -37,35 +37,39 @@ function useFoo(cond) {
const $ = _c(5);
const sourceDep = 0;
let t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = identity(0);
$[0] = t0;
t1 = identity(0);
$[0] = t1;
} else {
t0 = $[0];
t1 = $[0];
}
t0 = t1;
const derived1 = t0;
const derived2 = (cond ?? Math.min(0, 1)) ? 1 : 2;
let t1;
let t2;
let t3;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = identity(0);
$[1] = t1;
t3 = identity(0);
$[1] = t3;
} else {
t1 = $[1];
t3 = $[1];
}
const derived3 = t1;
t2 = t3;
const derived3 = t2;
const derived4 = (Math.min(0, -1) ?? cond) ? 1 : 2;
let t2;
let t4;
if ($[2] !== derived2 || $[3] !== derived4) {
t2 = [derived1, derived2, derived3, derived4];
t4 = [derived1, derived2, derived3, derived4];
$[2] = derived2;
$[3] = derived4;
$[4] = t2;
$[4] = t4;
} else {
t2 = $[4];
t4 = $[4];
}
return t2;
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -48,13 +48,15 @@ function Foo(props) {
}
const x = t0;
let t1;
let t2;
if ($[2] !== x[0]) {
t1 = [x[0]];
t2 = [x[0]];
$[2] = x[0];
$[3] = t1;
$[3] = t2;
} else {
t1 = $[3];
t2 = $[3];
}
t1 = t2;
return t1;
}

View File

@@ -42,17 +42,19 @@ function useFoo(minWidth, otherProp) {
let t0;
if ($[0] !== minWidth || $[1] !== otherProp || $[2] !== width) {
const x = [];
let t1;
const t1 = Math.max(minWidth, width);
let t2;
if ($[4] !== t1) {
t2 = { width: t1 };
$[4] = t1;
$[5] = t2;
const t2 = Math.max(minWidth, width);
let t3;
if ($[4] !== t2) {
t3 = { width: t2 };
$[4] = t2;
$[5] = t3;
} else {
t2 = $[5];
t3 = $[5];
}
const style = t2;
t1 = t3;
const style = t1;
arrayPush(x, otherProp);
t0 = [style, x];

View File

@@ -29,13 +29,15 @@ import { useMemo } from "react";
function useFoo(a, b) {
const $ = _c(2);
let t0;
let t1;
if ($[0] !== a) {
t0 = [a];
t1 = [a];
$[0] = a;
$[1] = t0;
$[1] = t1;
} else {
t0 = $[1];
t1 = $[1];
}
t0 = t1;
return t0;
}

View File

@@ -37,13 +37,15 @@ import { useMemo } from "react";
function useHook(x) {
const $ = _c(2);
let t0;
let t1;
if ($[0] !== x.y.z) {
t0 = [x.y.z];
t1 = [x.y.z];
$[0] = x.y.z;
$[1] = t0;
$[1] = t1;
} else {
t0 = $[1];
t1 = $[1];
}
t0 = t1;
return t0;
}

View File

@@ -29,7 +29,9 @@ import { useMemo } from "react";
// It's correct to infer a useMemo value is non-allocating
// and not provide it with a reactive scope
function useFoo(num1, num2) {
return Math.min(num1, num2);
let t0;
t0 = Math.min(num1, num2);
return t0;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -31,12 +31,14 @@ import { CONST_STRING0 } from "shared-runtime";
function useFoo() {
const $ = _c(1);
let t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [CONST_STRING0];
$[0] = t0;
t1 = [CONST_STRING0];
$[0] = t1;
} else {
t0 = $[0];
t1 = $[0];
}
t0 = t1;
return t0;
}

View File

@@ -30,23 +30,25 @@ import { identity } from "shared-runtime";
function useFoo(data) {
const $ = _c(4);
let t0;
if ($[0] !== data.a) {
t0 = identity(data.a);
$[0] = data.a;
$[1] = t0;
} else {
t0 = $[1];
}
const temp = t0;
let t1;
if ($[2] !== temp) {
t1 = { temp };
$[2] = temp;
$[3] = t1;
if ($[0] !== data.a) {
t1 = identity(data.a);
$[0] = data.a;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
return t1;
const temp = t1;
let t2;
if ($[2] !== temp) {
t2 = { temp };
$[2] = temp;
$[3] = t2;
} else {
t2 = $[3];
}
t0 = t2;
return t0;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -35,13 +35,15 @@ function useFoo(t0) {
const $ = _c(2);
const { callback } = t0;
let t1;
let t2;
if ($[0] !== callback) {
t1 = new Array(callback());
t2 = new Array(callback());
$[0] = callback;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
return t1;
}

View File

@@ -50,13 +50,15 @@ function useFoo(arr1, arr2) {
y = $[4];
}
let t1;
let t2;
if ($[5] !== y) {
t1 = { y };
t2 = { y };
$[5] = y;
$[6] = t1;
$[6] = t2;
} else {
t1 = $[6];
t2 = $[6];
}
t1 = t2;
return t1;
}

View File

@@ -49,12 +49,14 @@ function Foo(t0) {
let y = [];
let t2;
let t3;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t2 = { x: 2 };
$[5] = t2;
t3 = { x: 2 };
$[5] = t3;
} else {
t2 = $[5];
t3 = $[5];
}
t2 = t3;
val1 = t2;
foo ? (y = x.concat(arr2)) : y;

View File

@@ -33,13 +33,15 @@ function Component(t0) {
const $ = _c(2);
const { propA } = t0;
let t1;
let t2;
if ($[0] !== propA) {
t1 = [propA];
t2 = [propA];
$[0] = propA;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
return t1;
}

View File

@@ -42,34 +42,36 @@ function Component(t0) {
arg?.items.edges?.nodes;
let t1;
let t2;
if ($[0] !== arg?.items.edges?.nodes) {
t1 = arg?.items.edges?.nodes.map(identity);
t2 = arg?.items.edges?.nodes.map(identity);
$[0] = arg?.items.edges?.nodes;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
t1 = t2;
const data = t1;
const t2 = arg?.items.edges?.nodes;
let t3;
if ($[2] !== t2) {
t3 = [t2];
$[2] = t2;
$[3] = t3;
} else {
t3 = $[3];
}
const t3 = arg?.items.edges?.nodes;
let t4;
if ($[4] !== data || $[5] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={data} />;
$[4] = data;
$[5] = t3;
$[6] = t4;
if ($[2] !== t3) {
t4 = [t3];
$[2] = t3;
$[3] = t4;
} else {
t4 = $[6];
t4 = $[3];
}
return t4;
let t5;
if ($[4] !== data || $[5] !== t4) {
t5 = <ValidateMemoization inputs={t4} output={data} />;
$[4] = data;
$[5] = t4;
$[6] = t5;
} else {
t5 = $[6];
}
return t5;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -23,19 +23,21 @@ import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMe
import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(2);
let t0;
const x$0 = [];
x$0.push(props?.a.b?.c.d?.e);
x$0.push(props.a?.b.c?.d.e);
let t0;
t0 = x$0;
let t1;
if ($[0] !== props.a.b.c.d.e) {
t0 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;
t1 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;
$[0] = props.a.b.c.d.e;
$[1] = t0;
$[1] = t1;
} else {
t0 = $[1];
t1 = $[1];
}
return t0;
return t1;
}
```

View File

@@ -23,6 +23,7 @@ import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMe
import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(7);
let t0;
let x;
if ($[0] !== props.items) {
x = [];
@@ -33,25 +34,26 @@ function Component(props) {
} else {
x = $[1];
}
const data = x;
let t0;
if ($[2] !== props.items) {
t0 = [props.items];
$[2] = props.items;
$[3] = t0;
} else {
t0 = $[3];
}
t0 = x;
const data = t0;
let t1;
if ($[4] !== data || $[5] !== t0) {
t1 = <ValidateMemoization inputs={t0} output={data} />;
$[4] = data;
$[5] = t0;
$[6] = t1;
if ($[2] !== props.items) {
t1 = [props.items];
$[2] = props.items;
$[3] = t1;
} else {
t1 = $[6];
t1 = $[3];
}
return t1;
let t2;
if ($[4] !== data || $[5] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={data} />;
$[4] = data;
$[5] = t1;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
```

View File

@@ -38,6 +38,7 @@ function Component(t0) {
const { arg } = t0;
arg?.items;
let t1;
let x;
if ($[0] !== arg?.items) {
x = [];
@@ -47,26 +48,27 @@ function Component(t0) {
} else {
x = $[1];
}
const data = x;
const t1 = arg?.items;
let t2;
if ($[2] !== t1) {
t2 = [t1];
$[2] = t1;
$[3] = t2;
} else {
t2 = $[3];
}
t1 = x;
const data = t1;
const t2 = arg?.items;
let t3;
if ($[4] !== data || $[5] !== t2) {
t3 = <ValidateMemoization inputs={t2} output={data} />;
$[4] = data;
$[5] = t2;
$[6] = t3;
if ($[2] !== t2) {
t3 = [t2];
$[2] = t2;
$[3] = t3;
} else {
t3 = $[6];
t3 = $[3];
}
return t3;
let t4;
if ($[4] !== data || $[5] !== t3) {
t4 = <ValidateMemoization inputs={t3} output={data} />;
$[4] = data;
$[5] = t3;
$[6] = t4;
} else {
t4 = $[6];
}
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -31,32 +31,34 @@ import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c(7);
let t0;
if ($[0] !== props.x) {
t0 = props.x();
$[0] = props.x;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let t1;
if ($[2] !== props.x) {
t1 = [props.x];
$[2] = props.x;
$[3] = t1;
if ($[0] !== props.x) {
t1 = props.x();
$[0] = props.x;
$[1] = t1;
} else {
t1 = $[3];
t1 = $[1];
}
t0 = t1;
const x = t0;
let t2;
if ($[4] !== t1 || $[5] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[4] = t1;
$[5] = x;
$[6] = t2;
if ($[2] !== props.x) {
t2 = [props.x];
$[2] = props.x;
$[3] = t2;
} else {
t2 = $[6];
t2 = $[3];
}
return t2;
let t3;
if ($[4] !== t2 || $[5] !== x) {
t3 = <ValidateMemoization inputs={t2} output={x} />;
$[4] = t2;
$[5] = x;
$[6] = t3;
} else {
t3 = $[6];
}
return t3;
}
const f = () => ["React"];

View File

@@ -23,7 +23,9 @@ function foo(x) {
if (x <= 0) {
return 0;
}
return x + foo(x - 1) + foo(x - 2);
let t0;
t0 = foo(x - 2);
return x + foo(x - 1) + t0;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -59,46 +59,48 @@ function Component(t0) {
const $ = _c(9);
const { config } = t0;
let t1;
let t2;
if ($[0] !== config) {
t1 = (event) => {
t2 = (event) => {
config?.onA?.(event);
};
$[0] = config;
$[1] = t1;
$[1] = t2;
} else {
t1 = $[1];
t2 = $[1];
}
const a = t1;
let t2;
const a = t2;
let t3;
if ($[2] !== config) {
t2 = (event_0) => {
t3 = (event_0) => {
config?.onB?.(event_0);
};
$[2] = config;
$[3] = t2;
$[3] = t3;
} else {
t2 = $[3];
t3 = $[3];
}
const b = t2;
let t3;
const b = t3;
let t4;
if ($[4] !== a || $[5] !== b) {
t3 = { b, a };
t4 = { b, a };
$[4] = a;
$[5] = b;
$[6] = t3;
$[6] = t4;
} else {
t3 = $[6];
t4 = $[6];
}
const object = t3;
let t4;
t1 = t4;
const object = t1;
let t5;
if ($[7] !== object) {
t4 = <Stringify value={object} />;
t5 = <Stringify value={object} />;
$[7] = object;
$[8] = t4;
$[8] = t5;
} else {
t4 = $[8];
t5 = $[8];
}
return t4;
return t5;
}
```

View File

@@ -65,18 +65,20 @@ function Component() {
}
const filtered = t2;
let t3;
let t4;
if ($[6] !== filtered) {
t3 = filtered.map();
t4 = filtered.map();
$[6] = filtered;
$[7] = t3;
$[7] = t4;
} else {
t3 = $[7];
t4 = $[7];
}
t3 = t4;
const map = t3;
const index = filtered.findIndex(_temp3);
let t4;
let t5;
if ($[8] !== index || $[9] !== map) {
t4 = (
t5 = (
<div>
{map}
{index}
@@ -84,11 +86,11 @@ function Component() {
);
$[8] = index;
$[9] = map;
$[10] = t4;
$[10] = t5;
} else {
t4 = $[10];
t5 = $[10];
}
return t4;
return t5;
}
function _temp3(x) {
return x === null;

View File

@@ -62,18 +62,20 @@ function Component() {
}
const filtered = t2;
let t3;
let t4;
if ($[6] !== filtered) {
t3 = filtered.map();
t4 = filtered.map();
$[6] = filtered;
$[7] = t3;
$[7] = t4;
} else {
t3 = $[7];
t4 = $[7];
}
t3 = t4;
const map = t3;
const index = filtered.findIndex(_temp3);
let t4;
let t5;
if ($[8] !== index || $[9] !== map) {
t4 = (
t5 = (
<div>
{map}
{index}
@@ -81,11 +83,11 @@ function Component() {
);
$[8] = index;
$[9] = map;
$[10] = t4;
$[10] = t5;
} else {
t4 = $[10];
t5 = $[10];
}
return t4;
return t5;
}
function _temp3(x) {
return x === null;

View File

@@ -1,52 +0,0 @@
## Input
```javascript
function Component() {
let v3, v4, acc;
v3 = false;
v4 = v3;
acc = v3;
if (acc) {
acc = true;
v3 = acc;
}
if (acc) {
v3 = v4;
}
v4 = v3;
return [acc, v3, v4];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime";
function Component() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [false, false, false];
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};
```
### Eval output
(kind: ok) [false,false,false]

View File

@@ -1,20 +0,0 @@
function Component() {
let v3, v4, acc;
v3 = false;
v4 = v3;
acc = v3;
if (acc) {
acc = true;
v3 = acc;
}
if (acc) {
v3 = v4;
}
v4 = v3;
return [acc, v3, v4];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};

View File

@@ -39,51 +39,55 @@ function Component() {
```javascript
import { c as _c } from "react/compiler-runtime"; // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
function Component() {
const $ = _c(6);
const $ = _c(7);
const items = useItems();
let t0;
let t1;
let t2;
if ($[0] !== items) {
t1 = Symbol.for("react.early_return_sentinel");
t2 = Symbol.for("react.early_return_sentinel");
bb0: {
const filteredItems = items.filter(_temp);
t0 = items.filter(_temp);
const filteredItems = t0;
if (filteredItems.length === 0) {
let t2;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t2 = (
let t3;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t3 = (
<div>
<span />
</div>
);
$[3] = t2;
$[4] = t3;
} else {
t2 = $[3];
t3 = $[4];
}
t1 = t2;
t2 = t3;
break bb0;
}
t0 = filteredItems.map(_temp2);
t1 = filteredItems.map(_temp2);
}
$[0] = items;
$[1] = t0;
$[2] = t1;
$[1] = t1;
$[2] = t2;
$[3] = t0;
} else {
t0 = $[1];
t1 = $[2];
t1 = $[1];
t2 = $[2];
t0 = $[3];
}
if (t1 !== Symbol.for("react.early_return_sentinel")) {
return t1;
if (t2 !== Symbol.for("react.early_return_sentinel")) {
return t2;
}
let t2;
if ($[4] !== t0) {
t2 = <>{t0}</>;
$[4] = t0;
$[5] = t2;
let t3;
if ($[5] !== t1) {
t3 = <>{t1}</>;
$[5] = t1;
$[6] = t3;
} else {
t2 = $[5];
t3 = $[6];
}
return t2;
return t3;
}
function _temp2(t0) {
const [item_0] = t0;

View File

@@ -1,65 +0,0 @@
## Input
```javascript
import {Stringify, useIdentity} from 'shared-runtime';
function Component({other, ...props}, ref) {
[props, ref] = useIdentity([props, ref]);
return <Stringify props={props} />;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{a: 0, b: 'hello', children: <div>Hello</div>}],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime";
import { Stringify, useIdentity } from "shared-runtime";
function Component(t0, ref) {
const $ = _c(7);
let props;
if ($[0] !== t0) {
let { other, ...t1 } = t0;
props = t1;
$[0] = t0;
$[1] = props;
} else {
props = $[1];
}
let t1;
if ($[2] !== props || $[3] !== ref) {
t1 = [props, ref];
$[2] = props;
$[3] = ref;
$[4] = t1;
} else {
t1 = $[4];
}
[props, ref] = useIdentity(t1);
let t2;
if ($[5] !== props) {
t2 = <Stringify props={props} />;
$[5] = props;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 0, b: "hello", children: <div>Hello</div> }],
};
```
### Eval output
(kind: ok) <div>{"props":{"a":0,"b":"hello","children":{"type":"div","key":null,"props":{"children":"Hello"},"_owner":"[[ cyclic ref *3 ]]","_store":{}}}}</div>

View File

@@ -1,11 +0,0 @@
import {Stringify, useIdentity} from 'shared-runtime';
function Component({other, ...props}, ref) {
[props, ref] = useIdentity([props, ref]);
return <Stringify props={props} />;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{a: 0, b: 'hello', children: <div>Hello</div>}],
};

View File

@@ -45,83 +45,87 @@ import { Stringify, identity, makeArray, toJSON } from "shared-runtime";
import { useMemo } from "react";
function Component(props) {
const $ = _c(12);
const $ = _c(13);
let t0;
let t1;
let t2;
if ($[0] !== props) {
t1 = Symbol.for("react.early_return_sentinel");
t2 = Symbol.for("react.early_return_sentinel");
bb0: {
const propsString = toJSON(props);
t0 = toJSON(props);
const propsString = t0;
if (propsString.length <= 2) {
t1 = null;
t2 = null;
break bb0;
}
t0 = identity(propsString);
t1 = identity(propsString);
}
$[0] = props;
$[1] = t0;
$[2] = t1;
} else {
t0 = $[1];
t1 = $[2];
}
if (t1 !== Symbol.for("react.early_return_sentinel")) {
return t1;
}
let t2;
if ($[3] !== t0) {
t2 = { url: t0 };
$[1] = t1;
$[2] = t2;
$[3] = t0;
$[4] = t2;
} else {
t2 = $[4];
t1 = $[1];
t2 = $[2];
t0 = $[3];
}
if (t2 !== Symbol.for("react.early_return_sentinel")) {
return t2;
}
const linkProps = t2;
let t3;
if ($[5] !== linkProps) {
if ($[4] !== t1) {
t3 = { url: t1 };
$[4] = t1;
$[5] = t3;
} else {
t3 = $[5];
}
const linkProps = t3;
let t4;
if ($[6] !== linkProps) {
const x = {};
let t4;
let t5;
let t6;
let t7;
let t8;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t4 = [1];
t5 = [2];
t6 = [3];
t7 = [4];
t8 = [5];
$[7] = t4;
let t9;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t5 = [1];
t6 = [2];
t7 = [3];
t8 = [4];
t9 = [5];
$[8] = t5;
$[9] = t6;
$[10] = t7;
$[11] = t8;
$[12] = t9;
} else {
t4 = $[7];
t5 = $[8];
t6 = $[9];
t7 = $[10];
t8 = $[11];
t9 = $[12];
}
t3 = (
t4 = (
<Stringify
link={linkProps}
val1={t4}
val2={t5}
val3={t6}
val4={t7}
val5={t8}
val1={t5}
val2={t6}
val3={t7}
val4={t8}
val5={t9}
>
{makeArray(x, 2)}
</Stringify>
);
$[5] = linkProps;
$[6] = t3;
$[6] = linkProps;
$[7] = t4;
} else {
t3 = $[6];
t4 = $[7];
}
return t3;
return t4;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -24,9 +24,10 @@ function Component(props) {
```javascript
import { c as _c } from "react/compiler-runtime";
function Component(props) {
const $ = _c(6);
const $ = _c(7);
const item = props.item;
let baseVideos;
let t0;
let thumbnails;
if ($[0] !== item) {
thumbnails = [];
@@ -40,21 +41,24 @@ function Component(props) {
});
$[0] = item;
$[1] = baseVideos;
$[2] = thumbnails;
$[2] = t0;
$[3] = thumbnails;
} else {
baseVideos = $[1];
thumbnails = $[2];
t0 = $[2];
thumbnails = $[3];
}
let t0;
if ($[3] !== baseVideos || $[4] !== thumbnails) {
t0 = <FlatList baseVideos={baseVideos} items={thumbnails} />;
$[3] = baseVideos;
$[4] = thumbnails;
$[5] = t0;
t0 = undefined;
let t1;
if ($[4] !== baseVideos || $[5] !== thumbnails) {
t1 = <FlatList baseVideos={baseVideos} items={thumbnails} />;
$[4] = baseVideos;
$[5] = thumbnails;
$[6] = t1;
} else {
t0 = $[5];
t1 = $[6];
}
return t0;
return t1;
}
```

View File

@@ -50,8 +50,10 @@ function Component(props) {
case 1: {
break bb0;
}
case 2:
default:
case 2: {
}
default: {
}
}
} else {
if (props.cond2) {

View File

@@ -41,7 +41,8 @@ function foo() {
case 2: {
break bb0;
}
default:
default: {
}
}
}

View File

@@ -43,17 +43,22 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
function foo(x) {
bb0: switch (x) {
case 0:
case 1:
case 0: {
}
case 1: {
}
case 2: {
break bb0;
}
case 3: {
break bb0;
}
case 4:
case 5:
default:
case 4: {
}
case 5: {
}
default: {
}
}
}

Some files were not shown because too many files have changed in this diff Show More