Status

Overall: 1724/1724 passing, 0 failed. All passes ported through ValidatePreservedManualMemoization (#48). Codegen (#49) fully ported. Code comparison: 1724/1724.

Snap (end-to-end): 1725/1725 passed, 0 failed

Transformation passes

HIR: partial (1651/1653, 2 failures — block ID ordering) PruneMaybeThrows: complete (1651/1651, includes 2nd call) DropManualMemoization: complete MergeConsecutiveBlocks: complete SSA: complete (1650/1650) EliminateRedundantPhi: complete ConstantPropagation: complete InferTypes: complete OptimizePropsMethodCalls: complete AnalyseFunctions: complete (1649/1649) InferMutationAliasingEffects: complete (1643/1643) OptimizeForSSR: complete (5/5, conditional, outputMode === 'ssr') DeadCodeElimination: complete InferMutationAliasingRanges: complete InferReactivePlaces: complete ValidateExhaustiveDependencies: complete RewriteInstructionKindsBasedOnReassignment: complete InferReactiveScopeVariables: complete MemoizeFbtAndMacroOperandsInSameScope: complete outlineJSX: complete (conditional on enableJsxOutlining) NameAnonymousFunctions: complete (2/2, conditional) OutlineFunctions: complete AlignMethodCallScopes: complete AlignObjectMethodScopes: complete PruneUnusedLabelsHIR: complete AlignReactiveScopesToBlockScopesHIR: complete MergeOverlappingReactiveScopesHIR: complete BuildReactiveScopeTerminalsHIR: complete FlattenReactiveLoopsHIR: complete FlattenScopesWithHooksOrUseHIR: complete PropagateScopeDependenciesHIR: complete BuildReactiveFunction: complete AssertWellFormedBreakTargets: complete PruneUnusedLabels: complete AssertScopeInstructionsWithinScopes: complete PruneNonEscapingScopes: complete PruneNonReactiveDependencies: complete PruneUnusedScopes: complete MergeReactiveScopesThatInvalidateTogether: complete PruneAlwaysInvalidatingScopes: complete PropagateEarlyReturns: complete PruneUnusedLValues: complete PromoteUsedTemporaries: complete ExtractScopeDeclarationsFromDestructuring: complete StabilizeBlockIds: complete RenameVariables: complete PruneHoistedContexts: complete ValidatePreservedManualMemoization: complete Codegen: complete (1717/1717 code comparison)

Logs

20260401-120000 Extend test-e2e with event comparison and fix bugs

Extended test-e2e.sh to compare logEvent() calls across all frontends (babel, swc, oxc) against the TS baseline. Added --json flag to e2e CLI binary to expose logger events. Fixed two bugs found by the new comparison: (1) TS Program.ts logged directive as [object Object] instead of its string value. (2) Rust program.rs used inferred fn_name for CompileSuccess instead of codegen_fn.id, causing arrow functions to report names the TS compiler doesn't. Removed all code output normalization from test-e2e.ts — comparison now uses prettier only.

20260331-230000 Fix ValidateSourceLocations error count discrepancy

Fixed 4 issues causing the Rust compiler to report 27 errors vs TS's 22 on the error.todo-missing-source-locations fixture: (1) Don't record the root function node as important (TS func.traverse visits descendants only). (2) Use make_var_declarator for hoisted scope declarations to reconstruct VariableDeclarator source locations. (3) Pass HIR pattern source locations through to generated ArrayPattern/ObjectPattern AST nodes. (4) Sort validation errors by source position for deterministic output. yarn snap --rust now 1725/1725 (was 1724/1725).

20260331-220000 Port ValidateSourceLocations to Rust compiler

Ported the test-only ValidateSourceLocations pass from TypeScript to Rust. This post-codegen validation checks that important source locations (used by Istanbul coverage instrumentation) are preserved in compiled output. Enabled via @validateSourceLocations pragma. The pass traverses both the original Babel AST function and the generated CodegenFunction output, comparing source locations for important node types. Code comparison now 1724/1724 (was 1723/1724) since both TS and Rust correctly error on error.todo-missing-source-locations.

20260331-210000 Fix function name inference to match TS parent-checking behavior

Fixed FunctionDiscoveryVisitor to only infer declarator names for direct function inits, matching TS's path.parentPath.isVariableDeclarator() check. Previously current_declarator_name leaked to all descendant functions (e.g., arrows nested inside object literals). Now the name is explicitly scoped: set only for function/arrow/call inits, cleared in non-forwardRef/memo call expressions, and cleared after forwardRef/memo calls finish processing arguments. 1723/1723 passing.

20260331-200000 Fix CompilerDiagnostic::todo() to produce ErrorDetail variant

Removed the flat-loc serialization hack from log_error, compiler_error_to_info, and log_errors_as_events. Instead fixed the root cause: the From for CompilerError impl now converts Todo-category diagnostics to CompilerErrorOrDiagnostic::ErrorDetail (matching TS's CompilerError.throwTodo() → CompilerErrorDetail). Invariant-category diagnostics remain as CompilerErrorOrDiagnostic::Diagnostic with sub-details (matching TS). 1723/1723 passing.

20260331-190000 Fix inner function debug log flushing and todo error event format

Fixed 2 pre-existing test failures. (1) In pipeline.rs, inner function debug logs were lost when analyse_functions errored because ? propagated before flushing logs. Fixed by capturing the result, flushing logs, then propagating. (2) CompilerDiagnostic::todo() produced nested error events while TS uses flat format with loc directly. Fixed by detecting flat diagnostics (single Error detail matching reason) and converting to flat format in log_error, compiler_error_to_info, and log_errors_as_events. 1722/1723 passing.

20260331-180000 Add MutVisitor trait and refactor AST mutation to use shared walker

Added MutVisitor trait with visit_statement/visit_expression/visit_identifier hooks and walk_program_mut/walk_statement_mut/walk_expression_mut free functions to react_compiler_ast. Refactored three groups of manual recursive AST walkers in program.rs (~780 lines) into three visitor structs: ReplaceFnVisitor, ReplaceWithGatedVisitor, RenameIdentifierVisitor (~110 lines). No test regressions (1721/1723).

20260329-120000 Static base registries for ShapeRegistry and GlobalRegistry

Replaced ShapeRegistry and GlobalRegistry type aliases (HashMap) with newtype structs supporting a base+overlay pattern. Built-in shapes and globals are now initialized once via LazyLock and shared across all Environment instances. Environment::with_config creates lightweight overlay registries that point to the static base; custom hooks and lazily-resolved module types go into the overlay's extras map. Cloning registries (e.g. for_outlined_fn) now copies only the small extras map. ~18% overall Rust compiler speedup (1263ms → 1031ms across 1717 fixtures). No test regressions.

20260328-180000 Consolidate duplicated helper logic across Rust crates

Eliminated ~3,700 lines of duplicated helper code across 30 files. Created canonical shared implementations for: visitor ID wrappers (visitors.rs), debug printer formatting (new print.rs module), predicate helpers (MutableRange::contains, Effect::is_mutable, Environment methods), post_dominator_frontier (dominator.rs), is_react_like_name (environment.rs), and is_use_operator_type (lib.rs). Also created react_compiler_utils crate with generic DisjointSet. All 1717/1717 passing, no regressions.

20260318-111828 Initial orchestrator status

First run of orchestrator. 10 passes ported (HIR through OptimizePropsMethodCalls). All passes have failures: HIR (1), PruneMaybeThrows (2), DropManualMemoization (17), IIFE (153), MergeConsecutiveBlocks (153), SSA (198), EliminateRedundantPhi (198), ConstantPropagation (199), InferTypes (727), OptimizePropsMethodCalls (745).

20260318-134746 Fix HIR reserved-words error

Fixed error.reserved-words.ts failure. The BabelPlugin.ts catch block was missing the details array in the CompileError event for reserved word errors from scope serialization. HIR now 1717/1717, frontier moved to PruneMaybeThrows.

20260318-160000 Print inner functions in debug HIR output

Changed debug HIR printer (TS + Rust) to print full inner function bodies inline instead of loweredFunc: <HIRFunction> placeholder. Also removed Function #N: header. HIR regressed to 775/1717 as inner function differences are now visible.

20260318-210850 Fix inner function lowering bugs in HIR pass

Fixed multiple bugs exposed by the new inner function debug printing:

20260318-220322 Fix PruneMaybeThrows and validation pass failures

Fixed 15 failures at the PruneMaybeThrows frontier:

20260318-223712 Fix MergeConsecutiveBlocks and SSA failures

Fixed 39 failures (1 MergeConsecutiveBlocks + 38 SSA):

20260318-224340 Fix ConstantPropagation source location

Fixed PostfixUpdate constant propagation using the instruction loc instead of the previous constant's loc. Now uses prev_loc from the matched constant. ConstantPropagation 1651/1651, frontier moved to InferTypes (708 failures).

20260318-235832 Fix InferTypes pass — 708 failures resolved

Fixed all 708 InferTypes failures plus 1 OptimizePropsMethodCalls failure:

20260318-235832 Port AnalyseFunctions pass skeleton

Ported AnalyseFunctions pass (#11) from TypeScript. Created react_compiler_inference crate. Pass skeleton is correct but inner function analysis depends on sub-passes not yet ported. 1108/1651 passing (543 crash during inner function analysis). Commit: 92cc807a9f

20260319-014600 Fix InferMutationAliasingEffects effect inference bugs

Fixed legacy signature effects, inner function aliasingEffects population (Phase 2/3), context variable effect classification, and built-in method calleeEffects in globals.rs. Added mutableOnlyIfOperandsAreMutable optimization for Array methods. 968 passed (+12), AnalyseFunctions 1104/1108, InferMutationAliasingEffects 902/1104. Remaining failures need inferMutationAliasingRanges and aliasing config porting.

20260319-023425 Add aliasing signature configs and fix Apply effects

Added aliasing configs for Array.push, Array.map, Set.add, Object.entries/keys/values. Fixed spread argument self-capture and NewExpression callee mutation check. InferMutationAliasingEffects: 202→2 failures. 1168/1717 passing overall. Remaining 549 failures mostly from inner function analysis needing sub-passes.

20260319-025540 Port DeadCodeElimination pass

Ported DeadCodeElimination (#14) from TypeScript into react_compiler_optimization crate. Wired into pipeline and inner function analysis (lower_with_mutation_aliasing). DCE 1102/1102, 0 failures. Overall 1168/1717.

20260319-041553 Port PruneMaybeThrows (2nd) and InferMutationAliasingRanges

Added second PruneMaybeThrows call (#15) to pipeline. Ported InferMutationAliasingRanges (#16) — computes mutable ranges, Place effects, and function-level effects. Wired into pipeline and inner function analysis. InferMutationAliasingRanges 1181/1218 (37 failures from unported inferReactiveScopeVariables). Overall 1247/1717 (+79).

20260319-092045 Port InferReactivePlaces, RewriteInstructionKinds, InferReactiveScopeVariables

Ported three passes in parallel:

20260319-093515 Fix InferReactiveScopeVariables scope output

Added missing ReactiveScope fields (dependencies, declarations, reassignments, etc.). Fixed debug printer to output all scope fields matching TS format. Fixed DisjointSet ordering (HashMap→IndexMap) and scope loc computation. InferReactiveScopeVariables: 1033/1033 (100%). Overall 1099/1717. Remaining 618 failures in upstream passes, mainly InferReactivePlaces (397).

20260319-103726 Fix InferReactivePlaces — 397→173 failures

Fixed three bugs in InferReactivePlaces:

20260319-111719 Fix InferMutationAliasingEffects function expression Apply effects

Added function expression value tracking for Apply effects — when a callee is a locally-declared function expression with known aliasing effects, use its signature instead of falling through to the default "no signature" path. InferMutationAliasingEffects: 110→21 failures. Overall 1401/1717 (+84).

20260319-141741 Fix InferMutationAliasingEffects and InferMutationAliasingRanges bugs

Fixed MutationReason formatting (AssignCurrentProperty), PropertyStore type check (Type::Poly→Type::TypeVar), context/params effect ordering, and Switch/Try terminal operand effects. Overall 1518→1566 passing (+48).

20260319-160000 Fix top 10 correctness bug risks from ANALYSIS.md

Fixed 6 of the top 10 correctness bugs identified in the port fidelity review (bugs #1, #2, #9 were already fixed; #8 skipped per architecture doc guidance):

20260319-164422 Fix InferMutationAliasingRanges FunctionExpression/ObjectMethod operand handling

Added FunctionExpression and ObjectMethod arms to apply_operand_effects in infer_mutation_aliasing_ranges.rs. Context variables of inner functions now get their mutableRange.start fixup applied, preventing invalid [0:N] ranges. Overall 1566→1568 passing (+2).

20260319-183501 Fix AnalyseFunctions — all 1717 tests passing

Fixed three categories of bugs to clear AnalyseFunctions frontier:

20260319-201728 Fix While terminal successors and spread argument Todo check

Fixed terminal_successors for While terminals — was returning loop_block instead of test, causing phi node identifiers in subsequent blocks to never be initialized. Added spread argument Freeze effect Todo check matching TS computeEffectsForSignature. Added error check after outer infer_mutation_aliasing_effects in pipeline.rs. AnalyseFunctions: 6→1 failures, InferMutationAliasingEffects: 16→5 failures. Overall +5.

20260319-211815 Fix remaining test failures — all passes clean through InferMutationAliasingRanges

Fixed 8 remaining failures across AnalyseFunctions (1), InferMutationAliasingEffects (5), InferMutationAliasingRanges (2):

20260320-042126 Port all remaining HIR passes (#20-#31)

Ported 12 passes in a single session, completing all 31 HIR passes:

20260320-133636 Fix remaining failures: 375→80

Fixed 295 of 375 failures across multiple passes:

20260320-141021 Port validateNoDerivedComputationsInEffects_exp

Ported the experimental validateNoDerivedComputationsInEffects_exp validation pass from TypeScript to Rust. The 13 "ValidateNoSetStateInRender" failures were actually caused by this unported pass — the test harness misattributed them to the preceding pass. Created validate_no_derived_computations_in_effects.rs (1269 lines) in react_compiler_validation. Overall: 1650/1717 passing (96.1%), 67 failures remaining.

20260320-161141 Fix ValidateNoSetStateInEffects — port createControlDominators

Ported createControlDominators / isRefControlledBlock logic from ControlDominators.ts into validate_no_set_state_in_effects.rs. Added post-dominator frontier computation and phi-node predecessor block fallback. Fixes 1 failure (valid-setState-in-useEffect-controlled-by-ref-value.js). Overall: 1651/1717 passing (96.2%), 66 failures remaining.

20260320-171654 Fix upstream validation passes — 7 InferReactivePlaces failures resolved

Fixed 3 validation passes causing 7 failures misattributed to InferReactivePlaces:

20260320-201055 Fix multiple passes — 1658→1673 (+15 tests)

Three categories of fixes:

20260320-213855 Fix VED, PSDH, AlignObjectMethod — 1673→1695 (+22)

Removed VED error stripping (was hiding 18 legitimate errors) after fixing VED false positives via correct StartMemoize/FinishMemoize scoping of dependency collection. Fixed PSDH inner function traversal for nested FunctionExpressions. Fixed AlignObjectMethodScopes scope range accumulation (HashMap for min/max). Overall: 1695/1717 passing (98.7%), 22 failures remaining.

20260321-000048 Fix PSDH assumed-invoked functions and outline_jsx — 1695→1700 (+5)

Fixed PSDH get_assumed_invoked_functions to share temporaries map across inner function recursion. Fixed outline_jsx: aliasingEffects Some(vec![]) instead of None, IndexMap for prop ordering, skip all JSX instructions in outlined groups. Overall: 1700/1717 passing (99.0%), 17 failures remaining.

20260321-000048 Fix OutlineFunctions and MergeOverlappingReactiveScopesHIR — 1700→1709 (+9)

Fixed outline_jsx block rewrite to place replacement at LAST JSX position (matching TS reverse iteration). Fixed MergeOverlappingReactiveScopesHIR scope deduplication to preserve insertion order instead of sorting by ScopeId. All OutlineFunctions and MergeOverlapping passes now clean. Remaining 8 failures: PSDH scope declarations (5), error reporting from unported reactive passes (3). Overall: 1709/1717 passing (99.5%), 8 failures remaining.

20260321-010000 Fix PropagateScopeDependenciesHIR — 1709→1713 (+4)

Fixed two bugs in PSDH:

20260320-213806 Port all reactive passes after BuildReactiveFunction

Ported 15 reactive passes + visitor infrastructure from TypeScript to Rust:

20260323-130614 Fix RenameVariables, ExtractScopeDeclarations, PruneNonEscapingScopes — 36→13 failures

Fixed 23 test failures across three passes:

20260323-160933 Fix 11 failures, add Result support to ReactiveFunctionTransform

Fixed 11 test failures (13→2 remaining):

Refactored ReactiveFunctionTransform trait to return Result<..., CompilerError> on all methods, enabling proper error propagation. Removed all .unwrap() calls on transform_reactive_function — callers propagate with ?. Overall: 1715/1717 passing (99.9%), 2 failures remaining (block ID ordering).

20260323-201154 Implement apply_compiled_functions — codegen application

Implemented the full codegen application pipeline so the Rust compiler now produces actual compiled JavaScript output instead of returning the original source:

20260324-210207 Fix outlined ordering, type annotations, script source type — 130→110 code failures

Fixed three categories of code comparison failures:

20260324-214542 Implement gating codegen — 110→96 code failures

Implemented function gating for the Rust compiler port:

20260324-233646 Port ValidatePreservedManualMemoization — 96→38 code failures

Ported ValidatePreservedManualMemoization from TypeScript to Rust (~440 lines). Validates that compiled output preserves manual useMemo/useCallback memoization:

20260325-011107 Fix error handling, enum passthrough, codegen invariants — 38→30 code failures

Fixed 8 code comparison failures:

20260325-123533 Fix JSX outlining, function discovery, gating — 32→14 code failures

Two parallel fixes:

  1. JSX outlining: re-compile outlined functions through full pipeline (create fresh Environment, build synthetic AST, lower to HIR, run all passes). All 9 jsx-outlining-* fixtures pass.
  2. Function discovery: add ExpressionStatement + deep expression recursion to AST replacement/ gating/rename traversals. Fix infer mode for React.memo/forwardRef, nested arrows in exports, gating edge cases. Commits: 526eced507 (function discovery), plus outstanding environment.rs changes. Code: 1687→1703 (99.2%). 14 remaining.

20260325-145443 Fix all remaining failures — 1717/1717 pass + code (100%)

Fixed final 14 code failures + 1 pass-level failure:

20260328-235900 Remove local visitor copies — use canonical react_compiler_hir::visitors

Replaced ~1,800 lines of duplicated visitor/iterator match logic across 21 files with calls to canonical react_compiler_hir::visitors functions. Remaining local functions are thin wrappers (e.g., calling canonical and mapping PlaceIdentifierId). Added each_instruction_value_operand_with_functions to canonical visitors for split-borrow cases. All 1717 tests still passing. Pass 1717/1717, Code 1717/1717.

20260330-134202 Fix 30 snap test failures — validation, codegen, prefilter

Fixed 30 snap test failures across multiple categories:

20260330-145244 Fix remaining snap failures — 1717/1718 (99.9%)

Fixed 10 more snap test failures:

20260331-220427 Port OptimizeForSSR pass

Ported OptimizeForSSR (#13) from TypeScript to Rust. The pass optimizes components for SSR by inlining useState/useReducer, removing effects and event handlers, and stripping known event handler/ref props from builtin JSX. Gated on outputMode === 'ssr'. Created optimize_for_ssr.rs in react_compiler_optimization crate. Added is_plain_object_type and is_start_transition_type helpers to react_compiler_hir. test-rust-port: 1724/1724, Snap --rust: 1725/1725.

20260402-103329 Fix e2e diagnostic event mismatches — 123→2 failures

Fixed 121 of 123 babel e2e test failures (diagnostic events only, no code changes):

20260401-105521 Move error formatting to Rust, fix JSXAttribute loc in codegen

Moved error formatting from JS to Rust: added code_frame.rs to react_compiler_diagnostics with code frame rendering and format_compiler_error(). Rust now returns pre-formatted error messages via formatted_message field on CompilerErrorInfo, eliminating ~160 lines of JS formatting code (formatCompilerError, categoryToHeading, printCodeFrame) and the @babel/code-frame dependency from babel-plugin-react-compiler-rust. Also fixed JSXExpressionContainer nodes in codegen to propagate source locations from place.loc, eliminating the ensureNodeLocs JS post-pass. test-rust-port: 1724/1724, Snap: 1725/1725, Snap --rust: 1725/1725.