diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts index a772be62aa..d10b74f661 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts @@ -7,7 +7,6 @@ import {NodePath, Scope} from '@babel/traverse'; import * as t from '@babel/types'; -import {Expression} from '@babel/types'; import invariant from 'invariant'; import { CompilerError, @@ -3365,7 +3364,7 @@ function lowerFunction( >, ): LoweredFunction | null { const componentScope: Scope = builder.parentFunction.scope; - const captured = gatherCapturedDeps(builder, expr, componentScope); + const capturedContext = gatherCapturedContext(expr, componentScope); /* * TODO(gsn): In the future, we could only pass in the context identifiers @@ -3379,7 +3378,7 @@ function lowerFunction( expr, builder.environment, builder.bindings, - [...builder.context, ...captured.identifiers], + [...builder.context, ...capturedContext], builder.parentFunction, ); let loweredFunc: HIRFunction; @@ -3392,7 +3391,6 @@ function lowerFunction( loweredFunc = lowering.unwrap(); return { func: loweredFunc, - dependencies: captured.refs, }; } @@ -4066,14 +4064,6 @@ function lowerAssignment( } } -function isValidDependency(path: NodePath): boolean { - const parent: NodePath = path.parentPath; - return ( - !path.node.computed && - !(parent.isCallExpression() && parent.get('callee') === path) - ); -} - function captureScopes({from, to}: {from: Scope; to: Scope}): Set { let scopes: Set = new Set(); while (from) { @@ -4088,8 +4078,7 @@ function captureScopes({from, to}: {from: Scope; to: Scope}): Set { return scopes; } -function gatherCapturedDeps( - builder: HIRBuilder, +function gatherCapturedContext( fn: NodePath< | t.FunctionExpression | t.ArrowFunctionExpression @@ -4097,10 +4086,8 @@ function gatherCapturedDeps( | t.ObjectMethod >, componentScope: Scope, -): {identifiers: Array; refs: Array} { - const capturedIds: Map = new Map(); - const capturedRefs: Set = new Set(); - const seenPaths: Set = new Set(); +): Array { + const capturedIds = new Set(); /* * Capture all the scopes from the parent of this function up to and including @@ -4111,33 +4098,11 @@ function gatherCapturedDeps( to: componentScope, }); - function addCapturedId(bindingIdentifier: t.Identifier): number { - if (!capturedIds.has(bindingIdentifier)) { - const index = capturedIds.size; - capturedIds.set(bindingIdentifier, index); - return index; - } else { - return capturedIds.get(bindingIdentifier)!; - } - } - function handleMaybeDependency( - path: - | NodePath - | NodePath - | NodePath, + path: NodePath | NodePath, ): void { // Base context variable to depend on let baseIdentifier: NodePath | NodePath; - /* - * Base expression to depend on, which (for now) may contain non side-effectful - * member expressions - */ - let dependency: - | NodePath - | NodePath - | NodePath - | NodePath; if (path.isJSXOpeningElement()) { const name = path.get('name'); if (!(name.isJSXMemberExpression() || name.isJSXIdentifier())) { @@ -4153,115 +4118,20 @@ function gatherCapturedDeps( 'Invalid logic in gatherCapturedDeps', ); baseIdentifier = current; - - /* - * Get the expression to depend on, which may involve PropertyLoads - * for member expressions - */ - let currentDep: - | NodePath - | NodePath - | NodePath = baseIdentifier; - - while (true) { - const nextDep: null | NodePath = currentDep.parentPath; - if (nextDep && nextDep.isJSXMemberExpression()) { - currentDep = nextDep; - } else { - break; - } - } - dependency = currentDep; - } else if (path.isMemberExpression()) { - // Calculate baseIdentifier - let currentId: NodePath = path; - while (currentId.isMemberExpression()) { - currentId = currentId.get('object'); - } - if (!currentId.isIdentifier()) { - return; - } - baseIdentifier = currentId; - - /* - * Get the expression to depend on, which may involve PropertyLoads - * for member expressions - */ - let currentDep: - | NodePath - | NodePath - | NodePath = baseIdentifier; - - while (true) { - const nextDep: null | NodePath = currentDep.parentPath; - if ( - nextDep && - nextDep.isMemberExpression() && - isValidDependency(nextDep) - ) { - currentDep = nextDep; - } else { - break; - } - } - - dependency = currentDep; } else { baseIdentifier = path; - dependency = path; } /* * Skip dependency path, as we already tried to recursively add it (+ all subexpressions) * as a dependency. */ - dependency.skip(); + path.skip(); // Add the base identifier binding as a dependency. const binding = baseIdentifier.scope.getBinding(baseIdentifier.node.name); - if (binding === undefined || !pureScopes.has(binding.scope)) { - return; - } - const idKey = String(addCapturedId(binding.identifier)); - - // Add the expression (potentially a memberexpr path) as a dependency. - let exprKey = idKey; - if (dependency.isMemberExpression()) { - let pathTokens = []; - let current: NodePath = dependency; - while (current.isMemberExpression()) { - const property = current.get('property') as NodePath; - pathTokens.push(property.node.name); - current = current.get('object'); - } - - exprKey += '.' + pathTokens.reverse().join('.'); - } else if (dependency.isJSXMemberExpression()) { - let pathTokens = []; - let current: NodePath = - dependency; - while (current.isJSXMemberExpression()) { - const property = current.get('property'); - pathTokens.push(property.node.name); - current = current.get('object'); - } - } - - if (!seenPaths.has(exprKey)) { - let loweredDep: Place; - if (dependency.isJSXIdentifier()) { - loweredDep = lowerValueToTemporary(builder, { - kind: 'LoadLocal', - place: lowerIdentifier(builder, dependency), - loc: path.node.loc ?? GeneratedSource, - }); - } else if (dependency.isJSXMemberExpression()) { - loweredDep = lowerJsxMemberExpression(builder, dependency); - } else { - loweredDep = lowerExpressionToTemporary(builder, dependency); - } - capturedRefs.add(loweredDep); - seenPaths.add(exprKey); + if (binding !== undefined && pureScopes.has(binding.scope)) { + capturedIds.add(binding.identifier); } } @@ -4292,13 +4162,13 @@ function gatherCapturedDeps( return; } else if (path.isJSXElement()) { handleMaybeDependency(path.get('openingElement')); - } else if (path.isMemberExpression() || path.isIdentifier()) { + } else if (path.isIdentifier()) { handleMaybeDependency(path); } }, }); - return {identifiers: [...capturedIds.keys()], refs: [...capturedRefs]}; + return [...capturedIds.keys()]; } function notNull(value: T | null): value is T { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts index d3c919a6d8..a422570fff 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts @@ -131,15 +131,7 @@ function collectHoistablePropertyLoadsImpl( fn: HIRFunction, context: CollectHoistablePropertyLoadsContext, ): ReadonlyMap { - const functionExpressionLoads = collectFunctionExpressionFakeLoads(fn); - const actuallyEvaluatedTemporaries = new Map( - [...context.temporaries].filter(([id]) => !functionExpressionLoads.has(id)), - ); - - const nodes = collectNonNullsInBlocks(fn, { - ...context, - temporaries: actuallyEvaluatedTemporaries, - }); + const nodes = collectNonNullsInBlocks(fn, context); propagateNonNull(fn, nodes, context.registry); if (DEBUG_PRINT) { @@ -598,30 +590,3 @@ function reduceMaybeOptionalChains( } } while (changed); } - -function collectFunctionExpressionFakeLoads( - fn: HIRFunction, -): Set { - const sources = new Map(); - const functionExpressionReferences = new Set(); - - for (const [_, block] of fn.body.blocks) { - for (const {lvalue, value} of block.instructions) { - if ( - value.kind === 'FunctionExpression' || - value.kind === 'ObjectMethod' - ) { - for (const reference of value.loweredFunc.dependencies) { - let curr: IdentifierId | undefined = reference.identifier.id; - while (curr != null) { - functionExpressionReferences.add(curr); - curr = sources.get(curr); - } - } - } else if (value.kind === 'PropertyLoad') { - sources.set(lvalue.identifier.id, value.object.identifier.id); - } - } - } - return functionExpressionReferences; -} diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index 31e42049fd..3248775f7c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -231,7 +231,6 @@ const EnvironmentConfigSchema = z.object({ enableUseTypeAnnotations: z.boolean().default(false), enableFunctionDependencyRewrite: z.boolean().default(true), - /** * Enables inlining ReactElement object literals in place of JSX * An alternative to the standard JSX transform which replaces JSX with React's jsxProd() runtime diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts index 263ec4c208..506db0e66e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts @@ -722,7 +722,6 @@ export type ObjectProperty = { }; export type LoweredFunction = { - dependencies: Array; func: HIRFunction; }; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts index 526ab7c7e5..1480ce1610 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts @@ -538,9 +538,6 @@ export function printInstructionValue(instrValue: ReactiveValue): string { .split('\n') .map(line => ` ${line}`) .join('\n'); - const deps = instrValue.loweredFunc.dependencies - .map(dep => printPlace(dep)) - .join(','); const context = instrValue.loweredFunc.func.context .map(dep => printPlace(dep)) .join(','); @@ -557,7 +554,7 @@ export function printInstructionValue(instrValue: ReactiveValue): string { }) .join(', ') ?? ''; const type = printType(instrValue.loweredFunc.func.returnType).trim(); - value = `${kind} ${name} @deps[${deps}] @context[${context}] @effects[${effects}]${type !== '' ? ` return${type}` : ''}:\n${fn}`; + value = `${kind} ${name} @context[${context}] @effects[${effects}]${type !== '' ? ` return${type}` : ''}:\n${fn}`; break; } case 'TaggedTemplateExpression': { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts index bd938db03e..2eb687dc87 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts @@ -690,9 +690,8 @@ function collectDependencies( } for (const instr of block.instructions) { if ( - fn.env.config.enableFunctionDependencyRewrite && - (instr.value.kind === 'FunctionExpression' || - instr.value.kind === 'ObjectMethod') + instr.value.kind === 'FunctionExpression' || + instr.value.kind === 'ObjectMethod' ) { context.declare(instr.lvalue.identifier, { id: instr.id, diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts index c9ee803bfa..49ff3c256e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts @@ -193,7 +193,7 @@ export function* eachInstructionValueOperand( } case 'ObjectMethod': case 'FunctionExpression': { - yield* instrValue.loweredFunc.dependencies; + yield* instrValue.loweredFunc.func.context; break; } case 'TaggedTemplateExpression': { @@ -517,8 +517,9 @@ export function mapInstructionValueOperands( } case 'ObjectMethod': case 'FunctionExpression': { - instrValue.loweredFunc.dependencies = - instrValue.loweredFunc.dependencies.map(d => fn(d)); + instrValue.loweredFunc.func.context = + instrValue.loweredFunc.func.context.map(d => fn(d)); + break; } case 'TaggedTemplateExpression': { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts index 684acaf298..1bdcd03c35 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts @@ -10,7 +10,6 @@ import { Effect, HIRFunction, Identifier, - IdentifierName, LoweredFunction, Place, isRefOrRefValue, @@ -41,20 +40,6 @@ export class IdentifierState { return identifier; } - declareProperty(lvalue: Place, object: Place, property: string): void { - const objectDependency = this.properties.get(object.identifier); - let nextDependency: Dependency; - if (objectDependency === undefined) { - nextDependency = {identifier: object.identifier, path: [property]}; - } else { - nextDependency = { - identifier: objectDependency.identifier, - path: [...objectDependency.path, property], - }; - } - this.properties.set(lvalue.identifier, nextDependency); - } - declareTemporary(lvalue: Place, value: Place): void { const resolved: Dependency = this.properties.get(value.identifier) ?? { identifier: value.identifier, @@ -73,25 +58,10 @@ export default function analyseFunctions(func: HIRFunction): void { case 'ObjectMethod': case 'FunctionExpression': { lower(instr.value.loweredFunc.func); - infer(instr.value.loweredFunc, state, func.context); - break; - } - case 'PropertyLoad': { - state.declareProperty( - instr.lvalue, - instr.value.object, - instr.value.property, - ); - break; - } - case 'ComputedLoad': { - /* - * The path is set to an empty string as the path doesn't really - * matter for a computed load. - */ - state.declareProperty(instr.lvalue, instr.value.object, ''); + infer(instr.value.loweredFunc, func.context); break; } + case 'LoadLocal': case 'LoadContext': { if (instr.lvalue.identifier.name === null) { @@ -115,11 +85,8 @@ function lower(func: HIRFunction): void { logHIRFunction('AnalyseFunction (inner)', func); } -function infer( - loweredFunc: LoweredFunction, - state: IdentifierState, - context: Array, -): void { +// infer loweredFunc (inner) with outer function context +function infer(loweredFunc: LoweredFunction, context: Array): void { const mutations = new Map(); for (const operand of loweredFunc.func.context) { if ( @@ -130,15 +97,13 @@ function infer( } } - for (const dep of loweredFunc.dependencies) { - let name: IdentifierName | null = null; - - if (state.properties.has(dep.identifier)) { - const receiver = state.properties.get(dep.identifier)!; - name = receiver.identifier.name; - } else { - name = dep.identifier.name; - } + for (const dep of loweredFunc.func.context) { + CompilerError.invariant(dep.identifier.name !== null, { + reason: 'context refs should always have a name', + description: null, + loc: dep.loc, + suggestions: null, + }); if (isRefOrRefValue(dep.identifier)) { /* @@ -149,8 +114,8 @@ function infer( * render */ dep.effect = Effect.Capture; - } else if (name !== null) { - const effect = mutations.get(name.value); + } else { + const effect = mutations.get(dep.identifier.name.value); if (effect !== undefined) { dep.effect = effect === Effect.Unknown ? Effect.Capture : effect; } @@ -176,7 +141,6 @@ function infer( const effect = mutations.get(place.identifier.name.value); if (effect !== undefined) { place.effect = effect === Effect.Unknown ? Effect.Capture : effect; - loweredFunc.dependencies.push(place); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableContextVariables.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableContextVariables.ts index 67babf43db..5d20a7fa75 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableContextVariables.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableContextVariables.ts @@ -61,22 +61,6 @@ export function inferMutableContextVariables(fn: HIRFunction): void { for (const [, block] of fn.body.blocks) { for (const instr of block.instructions) { switch (instr.value.kind) { - case 'PropertyLoad': { - state.declareProperty( - instr.lvalue, - instr.value.object, - instr.value.property, - ); - break; - } - case 'ComputedLoad': { - /* - * The path is set to an empty string as the path doesn't really - * matter for a computed load. - */ - state.declareProperty(instr.lvalue, instr.value.object, ''); - break; - } case 'LoadLocal': case 'LoadContext': { if (instr.lvalue.identifier.name === null) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts index e27b8f9521..5b700b23b4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts @@ -270,7 +270,6 @@ function emitSelectorFn(env: Environment, keys: Array): Instruction { name: null, loweredFunc: { func: fn, - dependencies: [], }, type: 'ArrowFunctionExpression', loc: GeneratedSource, diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts index 7a1473be40..0e6d1fd592 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts @@ -24,7 +24,6 @@ export function outlineFunctions( } if ( value.kind === 'FunctionExpression' && - value.loweredFunc.dependencies.length === 0 && value.loweredFunc.func.context.length === 0 && // TODO: handle outlining named functions value.loweredFunc.func.id === null && diff --git a/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts b/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts index bae038f9bd..4e8dc74419 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts @@ -7,12 +7,15 @@ import {CompilerError} from '../CompilerError'; import {BlockId, HIRFunction, Identifier, Place} from '../HIR/HIR'; +import {printHIR, printIdentifier} from '../HIR/PrintHIR'; import { eachInstructionLValue, eachInstructionOperand, eachTerminalOperand, } from '../HIR/visitors'; +const DEBUG = true; + /* * Pass to eliminate redundant phi nodes: * - all operands are the same identifier, ie `x2 = phi(x1, x1, x1)`. @@ -141,6 +144,23 @@ export function eliminateRedundantPhi( * have already propagated forwards since we visit in reverse postorder. */ } while (rewrites.size > size && hasBackEdge); + + if (DEBUG) { + for (const [, block] of ir.blocks) { + for (const phi of block.phis) { + CompilerError.invariant(!rewrites.has(phi.place.identifier), { + reason: '[EliminateRedundantPhis]: rewrite not complete', + loc: phi.place.loc, + }); + for (const [, operand] of phi.operands) { + CompilerError.invariant(!rewrites.has(operand.identifier), { + reason: '[EliminateRedundantPhis]: rewrite not complete', + loc: phi.place.loc, + }); + } + } + } + } } function rewritePlace( diff --git a/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts b/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts index caba0d3c36..820f7388dc 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts @@ -301,9 +301,6 @@ function enterSSAImpl( entry.preds.add(blockId); builder.defineFunction(loweredFunc); builder.enter(() => { - loweredFunc.context = loweredFunc.context.map(p => - builder.getPlace(p), - ); loweredFunc.params = loweredFunc.params.map(param => { if (param.kind === 'Identifier') { return builder.definePlace(param); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md index 37a510b8c2..3584faf699 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md @@ -44,48 +44,44 @@ import { c as _c } from "react/compiler-runtime"; // @validateRefAccessDuringRen import { useEffect, useRef, useState } from "react"; function Component() { - const $ = _c(6); + const $ = _c(5); const ref = useRef(null); const [state, setState] = useState(false); let t0; - let t1; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t0 = () => {}; - - t1 = []; + t0 = []; $[0] = t0; - $[1] = t1; } else { t0 = $[0]; - t1 = $[1]; } - useEffect(t0, t1); + useEffect(_temp, t0); + let t1; let t2; - let t3; - if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - t2 = () => { + if ($[1] === Symbol.for("react.memo_cache_sentinel")) { + t1 = () => { setState(true); }; - t3 = []; + t2 = []; + $[1] = t1; $[2] = t2; - $[3] = t3; } else { + t1 = $[1]; t2 = $[2]; - t3 = $[3]; } - useEffect(t2, t3); + useEffect(t1, t2); - const t4 = String(state); - let t5; - if ($[4] !== t4) { - t5 = ; + const t3 = String(state); + let t4; + if ($[3] !== t3) { + t4 = ; + $[3] = t3; $[4] = t4; - $[5] = t5; } else { - t5 = $[5]; + t4 = $[4]; } - return t5; + return t4; } +function _temp() {} function Child(t0) { const { ref } = t0; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.expect.md index c071d5d20e..6836544c5d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.expect.md @@ -27,7 +27,6 @@ export const FIXTURE_ENTRYPOINT = { import { c as _c } from "react/compiler-runtime"; function component(a, b) { const $ = _c(2); - const y = { b }; let z; if ($[0] !== a) { z = { a }; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.expect.md index aa32b3260e..14bf94e770 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.expect.md @@ -31,12 +31,20 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { c as _c } from "react/compiler-runtime"; function Component(t0) { - const $ = _c(3); + const $ = _c(5); const { a, b } = t0; let z; if ($[0] !== a || $[1] !== b) { z = { a }; - const y = { b }; + let t1; + if ($[3] !== b) { + t1 = { b }; + $[3] = b; + $[4] = t1; + } else { + t1 = $[4]; + } + const y = t1; const x = function () { z.a = 2; return Math.max(y.b, 0); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md index 1b91bc1a11..a071dddba6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md @@ -34,7 +34,6 @@ function component(a) { const x = { a }; y = {}; - y; y = x; mutate(y); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md index f4721a507f..2afc5fd25d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md @@ -31,7 +31,6 @@ function bar(a) { const x = [a]; y = {}; - y; y = x[0][1]; $[0] = a; $[1] = y; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md index 5c0be290a6..3e57b7dc7c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md @@ -37,8 +37,6 @@ function bar(a, b) { let t; t = {}; - y; - t; y = x[0][1]; t = x[1][0]; $[0] = a; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md index 34b927d91e..22728aaf43 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md @@ -31,7 +31,6 @@ function bar(a) { const x = [a]; y = {}; - y; y = x[0].a[1]; $[0] = a; $[1] = y; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md index 0978be54ac..60f829cdc4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md @@ -30,7 +30,6 @@ function bar(a) { const x = [a]; y = {}; - y; y = x[0]; $[0] = a; $[1] = y; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md index 1bdc1c09a3..299aa5a31d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md @@ -25,7 +25,6 @@ function component(a) { const x = { a }; y = 1; - y; y = x; mutate(y); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.expect.md index d17c934b3b..cf85967682 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.expect.md @@ -38,9 +38,8 @@ function useTest() { const t1 = (w = 42); const t2 = w; - - w; let t3; + w = 999; t3 = 2; t0 = makeArray(t1, t2, t3); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md index e42ea8ce93..04b6c4f17f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md @@ -19,10 +19,10 @@ function foo() { import { c as _c } from "react/compiler-runtime"; function foo() { const $ = _c(1); + + const getJSX = _temp; let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - const getJSX = () => ; - t0 = getJSX(); $[0] = t0; } else { @@ -31,6 +31,9 @@ function foo() { const result = t0; return result; } +function _temp() { + return ; +} ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md index 6686c0b530..60fe0808d9 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md @@ -23,13 +23,14 @@ export const FIXTURE_ENTRYPOINT = { ```javascript function foo() { - const f = () => { - console.log(42); - }; + const f = _temp; f(); return 42; } +function _temp() { + console.log(42); +} export const FIXTURE_ENTRYPOINT = { fn: foo, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.expect.md index 8ea2190480..8822eddcdb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.expect.md @@ -18,12 +18,10 @@ function Component(props) { import { c as _c } from "react/compiler-runtime"; function Component(props) { const $ = _c(1); + + const onEvent = _temp; let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - const onEvent = () => { - console.log(42); - }; - t0 = ; $[0] = t0; } else { @@ -31,6 +29,9 @@ function Component(props) { } return t0; } +function _temp() { + console.log(42); +} ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.expect.md index 3dc0dba27c..da3bb94ed5 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.expect.md @@ -34,9 +34,8 @@ function Component(props) { let Component; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { Component = Stringify; - - Component; let t0; + t0 = Component; Component = t0; $[0] = Component; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md index 2045ee7901..1ba0d59e17 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md @@ -24,13 +24,17 @@ export const FIXTURE_ENTRYPOINT = { ## Error ``` + 4 | } 5 | return baz(); // OK: FuncDecls are HoistableDeclarations that have both declaration and value hoisting - 6 | function baz() { +> 6 | function baz() { + | ^^^^^^^^^^^^^^^^ > 7 | return bar(); - | ^^^ Todo: Support functions with unreachable code that may contain hoisted declarations (7:7) - 8 | } + | ^^^^^^^^^^^^^^^^^ +> 8 | } + | ^^^^ Todo: Support functions with unreachable code that may contain hoisted declarations (6:8) 9 | } 10 | + 11 | export const FIXTURE_ENTRYPOINT = { ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.expect.md index fd03115be1..59ece61d4d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.expect.md @@ -22,7 +22,7 @@ function Component() { 4 | // NOTE: `i` is a context variable because it's reassigned and also referenced 5 | // within a closure, the `onClick` handler of each item > 6 | for (let i = MIN; i <= MAX; i += INCREMENT) { - | ^^^^^^^^^^^ Todo: Support for loops where the index variable is a context variable. `i` is a context variable (6:6) + | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. Found mutation of `i` (6:6) 7 | items.push( data.set(i)} />); 8 | } 9 | return items; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md index db3a192eaf..f66b970f00 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md @@ -22,7 +22,7 @@ function Component(props) { 7 | return hasErrors; 8 | } > 9 | return hasErrors(); - | ^^^^^^^^^ Invariant: [hoisting] Expected value for identifier to be initialized. hasErrors_0$16 (9:9) + | ^^^^^^^^^ Invariant: [hoisting] Expected value for identifier to be initialized. hasErrors_0$14 (9:9) 10 | } 11 | ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md index 74e01a72d5..a7d27bc381 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md @@ -25,10 +25,10 @@ import { c as _c } from "react/compiler-runtime"; import { Stringify } from "shared-runtime"; function useFoo() { const $ = _c(1); + + const callback = _temp; let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - const callback = () => ; - t0 = callback(); $[0] = t0; } else { @@ -36,6 +36,9 @@ function useFoo() { } return t0; } +function _temp() { + return ; +} export const FIXTURE_ENTRYPOINT = { fn: useFoo, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.expect.md index 22fa3b2e2a..e5ead2479d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.expect.md @@ -25,10 +25,10 @@ import { c as _c } from "react/compiler-runtime"; import * as SharedRuntime from "shared-runtime"; function useFoo() { const $ = _c(1); + + const callback = _temp; let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - const callback = () => ; - t0 = callback(); $[0] = t0; } else { @@ -36,6 +36,9 @@ function useFoo() { } return t0; } +function _temp() { + return ; +} export const FIXTURE_ENTRYPOINT = { fn: useFoo, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md index dfe941282e..59c5b92fa1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md @@ -26,7 +26,6 @@ function f(a) { const $ = _c(4); let x; if ($[0] !== a) { - x; x = { a }; $[0] = a; $[1] = x; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md index 2aa5d4d06d..8dc4839085 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md @@ -27,7 +27,6 @@ function f(a) { const $ = _c(2); let x; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x; x = {}; $[0] = x; } else { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.expect.md index 13ba6d1798..3c624de9eb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.expect.md @@ -31,7 +31,7 @@ function Component(props) { let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { t0 = (e) => { - setX((currentX) => currentX + null); + setX(_temp); }; $[0] = t0; } else { @@ -48,6 +48,9 @@ function Component(props) { } return t1; } +function _temp(currentX) { + return currentX + null; +} export const FIXTURE_ENTRYPOINT = { fn: Component, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.expect.md index dc1a87fe51..2f9cbb7750 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.expect.md @@ -35,7 +35,6 @@ function useFoo(arr1, arr2) { if ($[0] !== arr1 || $[1] !== arr2) { const x = [arr1]; - y; (y = x.concat(arr2)), y; $[0] = arr1; $[1] = arr2; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.expect.md index 2e451d8948..0c66dee6a8 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.expect.md @@ -22,26 +22,21 @@ function Component() { ## 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 = () => { - while (bar()) { - if (baz) { - bar(); - } - } - return () => 4; - }; - $[0] = t0; - } else { - t0 = $[0]; - } - const get4 = t0; + const get4 = _temp2; return get4; } +function _temp2() { + while (bar()) { + if (baz) { + bar(); + } + } + return _temp; +} +function _temp() { + return 4; +} ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.expect.md index ffa5f57b43..3fc047e292 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.expect.md @@ -85,7 +85,6 @@ function Inner(props) { input = use(FooContext); } - input; input; let t0; const t1 = input;