| 1 | # Status |
| 2 | |
| 3 | Overall: 1724/1724 passing, 0 failed. All passes ported through ValidatePreservedManualMemoization (#48). Codegen (#49) fully ported. Code comparison: 1724/1724. |
| 4 | |
| 5 | Snap (end-to-end): 1725/1725 passed, 0 failed |
| 6 | |
| 7 | ## Transformation passes |
| 8 | |
| 9 | HIR: partial (1651/1653, 2 failures — block ID ordering) |
| 10 | PruneMaybeThrows: complete (1651/1651, includes 2nd call) |
| 11 | DropManualMemoization: complete |
| 12 | MergeConsecutiveBlocks: complete |
| 13 | SSA: complete (1650/1650) |
| 14 | EliminateRedundantPhi: complete |
| 15 | ConstantPropagation: complete |
| 16 | InferTypes: complete |
| 17 | OptimizePropsMethodCalls: complete |
| 18 | AnalyseFunctions: complete (1649/1649) |
| 19 | InferMutationAliasingEffects: complete (1643/1643) |
| 20 | OptimizeForSSR: complete (5/5, conditional, outputMode === 'ssr') |
| 21 | DeadCodeElimination: complete |
| 22 | InferMutationAliasingRanges: complete |
| 23 | InferReactivePlaces: complete |
| 24 | ValidateExhaustiveDependencies: complete |
| 25 | RewriteInstructionKindsBasedOnReassignment: complete |
| 26 | InferReactiveScopeVariables: complete |
| 27 | MemoizeFbtAndMacroOperandsInSameScope: complete |
| 28 | outlineJSX: complete (conditional on enableJsxOutlining) |
| 29 | NameAnonymousFunctions: complete (2/2, conditional) |
| 30 | OutlineFunctions: complete |
| 31 | AlignMethodCallScopes: complete |
| 32 | AlignObjectMethodScopes: complete |
| 33 | PruneUnusedLabelsHIR: complete |
| 34 | AlignReactiveScopesToBlockScopesHIR: complete |
| 35 | MergeOverlappingReactiveScopesHIR: complete |
| 36 | BuildReactiveScopeTerminalsHIR: complete |
| 37 | FlattenReactiveLoopsHIR: complete |
| 38 | FlattenScopesWithHooksOrUseHIR: complete |
| 39 | PropagateScopeDependenciesHIR: complete |
| 40 | BuildReactiveFunction: complete |
| 41 | AssertWellFormedBreakTargets: complete |
| 42 | PruneUnusedLabels: complete |
| 43 | AssertScopeInstructionsWithinScopes: complete |
| 44 | PruneNonEscapingScopes: complete |
| 45 | PruneNonReactiveDependencies: complete |
| 46 | PruneUnusedScopes: complete |
| 47 | MergeReactiveScopesThatInvalidateTogether: complete |
| 48 | PruneAlwaysInvalidatingScopes: complete |
| 49 | PropagateEarlyReturns: complete |
| 50 | PruneUnusedLValues: complete |
| 51 | PromoteUsedTemporaries: complete |
| 52 | ExtractScopeDeclarationsFromDestructuring: complete |
| 53 | StabilizeBlockIds: complete |
| 54 | RenameVariables: complete |
| 55 | PruneHoistedContexts: complete |
| 56 | ValidatePreservedManualMemoization: complete |
| 57 | Codegen: complete (1717/1717 code comparison) |
| 58 | |
| 59 | # Logs |
| 60 | |
| 61 | ## 20260401-120000 Extend test-e2e with event comparison and fix bugs |
| 62 | |
| 63 | Extended test-e2e.sh to compare logEvent() calls across all frontends (babel, |
| 64 | swc, oxc) against the TS baseline. Added --json flag to e2e CLI binary to |
| 65 | expose logger events. Fixed two bugs found by the new comparison: (1) TS |
| 66 | Program.ts logged directive as [object Object] instead of its string value. |
| 67 | (2) Rust program.rs used inferred fn_name for CompileSuccess instead of |
| 68 | codegen_fn.id, causing arrow functions to report names the TS compiler doesn't. |
| 69 | Removed all code output normalization from test-e2e.ts — comparison now uses |
| 70 | prettier only. |
| 71 | |
| 72 | ## 20260331-230000 Fix ValidateSourceLocations error count discrepancy |
| 73 | |
| 74 | Fixed 4 issues causing the Rust compiler to report 27 errors vs TS's 22 on the |
| 75 | error.todo-missing-source-locations fixture: (1) Don't record the root function node as |
| 76 | important (TS func.traverse visits descendants only). (2) Use make_var_declarator for |
| 77 | hoisted scope declarations to reconstruct VariableDeclarator source locations. (3) Pass |
| 78 | HIR pattern source locations through to generated ArrayPattern/ObjectPattern AST nodes. |
| 79 | (4) Sort validation errors by source position for deterministic output. yarn snap --rust |
| 80 | now 1725/1725 (was 1724/1725). |
| 81 | |
| 82 | ## 20260331-220000 Port ValidateSourceLocations to Rust compiler |
| 83 | |
| 84 | Ported the test-only ValidateSourceLocations pass from TypeScript to Rust. This post-codegen |
| 85 | validation checks that important source locations (used by Istanbul coverage instrumentation) |
| 86 | are preserved in compiled output. Enabled via `@validateSourceLocations` pragma. The pass |
| 87 | traverses both the original Babel AST function and the generated CodegenFunction output, |
| 88 | comparing source locations for important node types. Code comparison now 1724/1724 (was |
| 89 | 1723/1724) since both TS and Rust correctly error on error.todo-missing-source-locations. |
| 90 | |
| 91 | ## 20260331-210000 Fix function name inference to match TS parent-checking behavior |
| 92 | |
| 93 | Fixed FunctionDiscoveryVisitor to only infer declarator names for direct function inits, |
| 94 | matching TS's path.parentPath.isVariableDeclarator() check. Previously current_declarator_name |
| 95 | leaked to all descendant functions (e.g., arrows nested inside object literals). Now the name |
| 96 | is explicitly scoped: set only for function/arrow/call inits, cleared in non-forwardRef/memo |
| 97 | call expressions, and cleared after forwardRef/memo calls finish processing arguments. |
| 98 | 1723/1723 passing. |
| 99 | |
| 100 | ## 20260331-200000 Fix CompilerDiagnostic::todo() to produce ErrorDetail variant |
| 101 | |
| 102 | Removed the flat-loc serialization hack from log_error, compiler_error_to_info, and |
| 103 | log_errors_as_events. Instead fixed the root cause: the From<CompilerDiagnostic> for |
| 104 | CompilerError impl now converts Todo-category diagnostics to CompilerErrorOrDiagnostic::ErrorDetail |
| 105 | (matching TS's CompilerError.throwTodo() → CompilerErrorDetail). Invariant-category |
| 106 | diagnostics remain as CompilerErrorOrDiagnostic::Diagnostic with sub-details (matching TS). |
| 107 | 1723/1723 passing. |
| 108 | |
| 109 | ## 20260331-190000 Fix inner function debug log flushing and todo error event format |
| 110 | |
| 111 | Fixed 2 pre-existing test failures. (1) In pipeline.rs, inner function debug logs were |
| 112 | lost when analyse_functions errored because `?` propagated before flushing logs. Fixed by |
| 113 | capturing the result, flushing logs, then propagating. (2) CompilerDiagnostic::todo() |
| 114 | produced nested error events while TS uses flat format with loc directly. Fixed by detecting |
| 115 | flat diagnostics (single Error detail matching reason) and converting to flat format in |
| 116 | log_error, compiler_error_to_info, and log_errors_as_events. 1722/1723 passing. |
| 117 | |
| 118 | ## 20260331-180000 Add MutVisitor trait and refactor AST mutation to use shared walker |
| 119 | |
| 120 | Added MutVisitor trait with visit_statement/visit_expression/visit_identifier hooks and |
| 121 | walk_program_mut/walk_statement_mut/walk_expression_mut free functions to react_compiler_ast. |
| 122 | Refactored three groups of manual recursive AST walkers in program.rs (~780 lines) into three |
| 123 | visitor structs: ReplaceFnVisitor, ReplaceWithGatedVisitor, RenameIdentifierVisitor (~110 lines). |
| 124 | No test regressions (1721/1723). |
| 125 | |
| 126 | ## 20260329-120000 Static base registries for ShapeRegistry and GlobalRegistry |
| 127 | |
| 128 | Replaced ShapeRegistry and GlobalRegistry type aliases (HashMap) with newtype structs |
| 129 | supporting a base+overlay pattern. Built-in shapes and globals are now initialized once |
| 130 | via LazyLock and shared across all Environment instances. Environment::with_config creates |
| 131 | lightweight overlay registries that point to the static base; custom hooks and lazily-resolved |
| 132 | module types go into the overlay's extras map. Cloning registries (e.g. for_outlined_fn) now |
| 133 | copies only the small extras map. ~18% overall Rust compiler speedup (1263ms → 1031ms across |
| 134 | 1717 fixtures). No test regressions. |
| 135 | |
| 136 | ## 20260328-180000 Consolidate duplicated helper logic across Rust crates |
| 137 | |
| 138 | Eliminated ~3,700 lines of duplicated helper code across 30 files. Created canonical |
| 139 | shared implementations for: visitor ID wrappers (visitors.rs), debug printer formatting |
| 140 | (new print.rs module), predicate helpers (MutableRange::contains, Effect::is_mutable, |
| 141 | Environment methods), post_dominator_frontier (dominator.rs), is_react_like_name |
| 142 | (environment.rs), and is_use_operator_type (lib.rs). Also created react_compiler_utils |
| 143 | crate with generic DisjointSet<K>. All 1717/1717 passing, no regressions. |
| 144 | |
| 145 | ## 20260318-111828 Initial orchestrator status |
| 146 | |
| 147 | First run of orchestrator. 10 passes ported (HIR through OptimizePropsMethodCalls). |
| 148 | All passes have failures: HIR (1), PruneMaybeThrows (2), DropManualMemoization (17), |
| 149 | IIFE (153), MergeConsecutiveBlocks (153), SSA (198), EliminateRedundantPhi (198), |
| 150 | ConstantPropagation (199), InferTypes (727), OptimizePropsMethodCalls (745). |
| 151 | |
| 152 | ## 20260318-134746 Fix HIR reserved-words error |
| 153 | |
| 154 | Fixed error.reserved-words.ts failure. The `BabelPlugin.ts` catch block was missing |
| 155 | the `details` array in the CompileError event for reserved word errors from scope serialization. |
| 156 | HIR now 1717/1717, frontier moved to PruneMaybeThrows. |
| 157 | |
| 158 | ## 20260318-160000 Print inner functions in debug HIR output |
| 159 | |
| 160 | Changed debug HIR printer (TS + Rust) to print full inner function bodies inline |
| 161 | instead of `loweredFunc: <HIRFunction>` placeholder. Also removed `Function #N:` header. |
| 162 | HIR regressed to 775/1717 as inner function differences are now visible. |
| 163 | |
| 164 | ## 20260318-210850 Fix inner function lowering bugs in HIR pass |
| 165 | |
| 166 | Fixed multiple bugs exposed by the new inner function debug printing: |
| 167 | - Removed extra `is_context_identifier` fallback in hir_builder.rs that incorrectly |
| 168 | emitted LoadContext instead of LoadLocal for non-context captured variables. |
| 169 | - Fixed source locations in gather_captured_context using IdentifierLocIndex lookup |
| 170 | instead of fabricated byte-offset-based locs. |
| 171 | - Changed ScopeInfo.reference_to_binding from HashMap to IndexMap for deterministic |
| 172 | insertion-order iteration matching Babel's traversal order. |
| 173 | - Added JSXOpeningElement loc tracking in identifier_loc_index for JSX context vars. |
| 174 | - Added node_type to UnsupportedNode for UpdateExpression and YieldExpression. |
| 175 | HIR now 1717/1717, frontier back to PruneMaybeThrows. |
| 176 | |
| 177 | ## 20260318-220322 Fix PruneMaybeThrows and validation pass failures |
| 178 | |
| 179 | Fixed 15 failures at the PruneMaybeThrows frontier: |
| 180 | - Fixed unreachable block predecessor tracking in hir_builder.rs (preds were empty instead of cloned). |
| 181 | - Implemented validateContextVariableLValues — errors were written to temp_errors and discarded. |
| 182 | - Fixed validateUseMemo VoidUseMemo event logging to include diagnostic details array. |
| 183 | - Fixed place formatting in invariant error descriptions to match TS printPlace() output. |
| 184 | PruneMaybeThrows now 1653/1653, DropManualMemoization 1652/1652, frontier moved to MergeConsecutiveBlocks. |
| 185 | |
| 186 | ## 20260318-223712 Fix MergeConsecutiveBlocks and SSA failures |
| 187 | |
| 188 | Fixed 39 failures (1 MergeConsecutiveBlocks + 38 SSA): |
| 189 | - Moved env.has_errors() bailout from before SSA to end of pipeline, matching TS behavior. |
| 190 | - Fixed SSA error event format (CompileUnexpectedThrow filtering, CompilerErrorDetail format). |
| 191 | - Fixed identifier formatting in SSA error descriptions to match TS printIdentifier() output. |
| 192 | - Added name$N normalization to test harness. |
| 193 | MergeConsecutiveBlocks 1652/1652, SSA 1651/1651, frontier moved to ConstantPropagation. |
| 194 | |
| 195 | ## 20260318-224340 Fix ConstantPropagation source location |
| 196 | |
| 197 | Fixed PostfixUpdate constant propagation using the instruction loc instead of the |
| 198 | previous constant's loc. Now uses prev_loc from the matched constant. |
| 199 | ConstantPropagation 1651/1651, frontier moved to InferTypes (708 failures). |
| 200 | |
| 201 | ## 20260318-235832 Fix InferTypes pass — 708 failures resolved |
| 202 | |
| 203 | Fixed all 708 InferTypes failures plus 1 OptimizePropsMethodCalls failure: |
| 204 | - Added `<generated_N>` shape ID normalization to test harness. |
| 205 | - Fixed built-in hook shape definitions (useState, useReducer, etc.) to use specific |
| 206 | indexed properties instead of wildcard-only shapes. |
| 207 | - Fixed React namespace to reuse built-in hook types instead of auto-generating new ones. |
| 208 | - Added console/global/globalThis typed properties to shape definitions. |
| 209 | - Implemented Reanimated module type provider. |
| 210 | - Fixed inner function global type pre-resolution and hook property name fallback. |
| 211 | - Implemented enableTreatSetIdentifiersAsStateSetters config support. |
| 212 | - Fixed validateHooksUsage error ordering for nested functions. |
| 213 | All 1717 tests passing, 0 failures. Next pass to port: #11 AnalyseFunctions. |
| 214 | |
| 215 | ## 20260318-235832 Port AnalyseFunctions pass skeleton |
| 216 | |
| 217 | Ported AnalyseFunctions pass (#11) from TypeScript. Created react_compiler_inference crate. |
| 218 | Pass skeleton is correct but inner function analysis depends on sub-passes not yet ported. |
| 219 | 1108/1651 passing (543 crash during inner function analysis). |
| 220 | Commit: 92cc807a9f |
| 221 | |
| 222 | ## 20260319-014600 Fix InferMutationAliasingEffects effect inference bugs |
| 223 | |
| 224 | Fixed legacy signature effects, inner function aliasingEffects population (Phase 2/3), |
| 225 | context variable effect classification, and built-in method calleeEffects in globals.rs. |
| 226 | Added mutableOnlyIfOperandsAreMutable optimization for Array methods. |
| 227 | 968 passed (+12), AnalyseFunctions 1104/1108, InferMutationAliasingEffects 902/1104. |
| 228 | Remaining failures need inferMutationAliasingRanges and aliasing config porting. |
| 229 | |
| 230 | ## 20260319-023425 Add aliasing signature configs and fix Apply effects |
| 231 | |
| 232 | Added aliasing configs for Array.push, Array.map, Set.add, Object.entries/keys/values. |
| 233 | Fixed spread argument self-capture and NewExpression callee mutation check. |
| 234 | InferMutationAliasingEffects: 202→2 failures. 1168/1717 passing overall. |
| 235 | Remaining 549 failures mostly from inner function analysis needing sub-passes. |
| 236 | |
| 237 | ## 20260319-025540 Port DeadCodeElimination pass |
| 238 | |
| 239 | Ported DeadCodeElimination (#14) from TypeScript into react_compiler_optimization crate. |
| 240 | Wired into pipeline and inner function analysis (lower_with_mutation_aliasing). |
| 241 | DCE 1102/1102, 0 failures. Overall 1168/1717. |
| 242 | |
| 243 | ## 20260319-041553 Port PruneMaybeThrows (2nd) and InferMutationAliasingRanges |
| 244 | |
| 245 | Added second PruneMaybeThrows call (#15) to pipeline. |
| 246 | Ported InferMutationAliasingRanges (#16) — computes mutable ranges, Place effects, |
| 247 | and function-level effects. Wired into pipeline and inner function analysis. |
| 248 | InferMutationAliasingRanges 1181/1218 (37 failures from unported inferReactiveScopeVariables). |
| 249 | Overall 1247/1717 (+79). |
| 250 | |
| 251 | ## 20260319-092045 Port InferReactivePlaces, RewriteInstructionKinds, InferReactiveScopeVariables |
| 252 | |
| 253 | Ported three passes in parallel: |
| 254 | - InferReactivePlaces (#17): 951/1169 (81.3%) — post-dominator frontier differences |
| 255 | - RewriteInstructionKindsBasedOnReassignment (#18): 943/951 (98.7%) |
| 256 | - InferReactiveScopeVariables (#19): 112/943 (11.9%) — major issues with scope assignment |
| 257 | Overall 179/1717. InferReactiveScopeVariables needs significant fixing. |
| 258 | |
| 259 | ## 20260319-093515 Fix InferReactiveScopeVariables scope output |
| 260 | |
| 261 | Added missing ReactiveScope fields (dependencies, declarations, reassignments, etc.). |
| 262 | Fixed debug printer to output all scope fields matching TS format. |
| 263 | Fixed DisjointSet ordering (HashMap→IndexMap) and scope loc computation. |
| 264 | InferReactiveScopeVariables: 1033/1033 (100%). Overall 1099/1717. |
| 265 | Remaining 618 failures in upstream passes, mainly InferReactivePlaces (397). |
| 266 | |
| 267 | ## 20260319-103726 Fix InferReactivePlaces — 397→173 failures |
| 268 | |
| 269 | Fixed three bugs in InferReactivePlaces: |
| 270 | - Added FunctionExpression/ObjectMethod context variables as operands for reactivity propagation. |
| 271 | - Fixed useRef stable type detection (Object type, not just Function). |
| 272 | - Separated value operand vs lvalue flag setting to avoid over-marking. |
| 273 | InferReactivePlaces 1270/1443 (173 failures). Overall 1316/1717 (+217). |
| 274 | |
| 275 | ## 20260319-111719 Fix InferMutationAliasingEffects function expression Apply effects |
| 276 | |
| 277 | Added function expression value tracking for Apply effects — when a callee is a |
| 278 | locally-declared function expression with known aliasing effects, use its signature |
| 279 | instead of falling through to the default "no signature" path. |
| 280 | InferMutationAliasingEffects: 110→21 failures. Overall 1401/1717 (+84). |
| 281 | |
| 282 | ## 20260319-141741 Fix InferMutationAliasingEffects and InferMutationAliasingRanges bugs |
| 283 | |
| 284 | Fixed MutationReason formatting (AssignCurrentProperty), PropertyStore type check |
| 285 | (Type::Poly→Type::TypeVar), context/params effect ordering, and Switch/Try terminal |
| 286 | operand effects. Overall 1518→1566 passing (+48). |
| 287 | |
| 288 | ## 20260319-160000 Fix top 10 correctness bug risks from ANALYSIS.md |
| 289 | |
| 290 | Fixed 6 of the top 10 correctness bugs identified in the port fidelity review |
| 291 | (bugs #1, #2, #9 were already fixed; #8 skipped per architecture doc guidance): |
| 292 | - globals.rs: Array callback methods (filter, find, findIndex, forEach, every, some, |
| 293 | flatMap, reduce) changed from positionalParams to restParam, added noAlias: true. |
| 294 | - constant_propagation.rs: is_valid_identifier now rejects JS reserved words. |
| 295 | - constant_propagation.rs: js_abstract_equal uses proper JS ToNumber semantics. |
| 296 | - merge_consecutive_blocks.rs: phi replacement instructions include Alias effect. |
| 297 | - merge_consecutive_blocks.rs: recursive merge into inner FunctionExpression/ObjectMethod. |
| 298 | - infer_types.rs: context variable places on inner functions now type-resolved. |
| 299 | Overall 1566→1566 passing (+1 net after recount with updated baseline). |
| 300 | |
| 301 | ## 20260319-164422 Fix InferMutationAliasingRanges FunctionExpression/ObjectMethod operand handling |
| 302 | |
| 303 | Added FunctionExpression and ObjectMethod arms to apply_operand_effects in |
| 304 | infer_mutation_aliasing_ranges.rs. Context variables of inner functions now get |
| 305 | their mutableRange.start fixup applied, preventing invalid [0:N] ranges. |
| 306 | Overall 1566→1568 passing (+2). |
| 307 | |
| 308 | ## 20260319-183501 Fix AnalyseFunctions — all 1717 tests passing |
| 309 | |
| 310 | Fixed three categories of bugs to clear AnalyseFunctions frontier: |
| 311 | - globals.rs: BuiltInEffectEventFunction signature — rest_param and callee_effect |
| 312 | changed from Effect::Read to Effect::ConditionallyMutate, matching TS definition. |
| 313 | - infer_mutation_aliasing_effects.rs: Added transitive freeze of function expression |
| 314 | captures, uninitialized identifier access detection with correct source locations. |
| 315 | - infer_mutation_aliasing_ranges.rs: Context var effect defaulting — FunctionExpression |
| 316 | operands not in operandEffects now default to Effect::Read. |
| 317 | - analyse_functions.rs: Early return on invariant errors from inner function processing. |
| 318 | - pipeline.rs: Invariant error propagation after analyse_functions. |
| 319 | AnalyseFunctions: 1717/1717 (0 failures). Overall 1568→1577 passing (+9). |
| 320 | |
| 321 | ## 20260319-201728 Fix While terminal successors and spread argument Todo check |
| 322 | |
| 323 | Fixed `terminal_successors` for While terminals — was returning `loop_block` instead of |
| 324 | `test`, causing phi node identifiers in subsequent blocks to never be initialized. |
| 325 | Added spread argument Freeze effect Todo check matching TS `computeEffectsForSignature`. |
| 326 | Added error check after outer `infer_mutation_aliasing_effects` in pipeline.rs. |
| 327 | AnalyseFunctions: 6→1 failures, InferMutationAliasingEffects: 16→5 failures. Overall +5. |
| 328 | |
| 329 | ## 20260319-211815 Fix remaining test failures — all passes clean through InferMutationAliasingRanges |
| 330 | |
| 331 | Fixed 8 remaining failures across AnalyseFunctions (1), InferMutationAliasingEffects (5), |
| 332 | InferMutationAliasingRanges (2): |
| 333 | - Fixed CreateFrom reason selection (HashSet non-deterministic order → primary_reason helper). |
| 334 | - Added aliasing_config_temp_cache to prevent duplicate identifier allocation in fixpoint. |
| 335 | - Added mutable spread tracking to compute_effects_for_aliasing_signature_config. |
| 336 | - Fixed each_instruction_value_operands to yield FunctionExpression context variables. |
| 337 | All 1717 fixtures passing through InferMutationAliasingRanges. Frontier: null (all clean). |
| 338 | Next: port passes #20+ (MemoizeFbtAndMacroOperandsInSameScope onwards). |
| 339 | |
| 340 | ## 20260320-042126 Port all remaining HIR passes (#20-#31) |
| 341 | |
| 342 | Ported 12 passes in a single session, completing all 31 HIR passes: |
| 343 | - #20 MemoizeFbtAndMacroOperandsInSameScope (662 lines) |
| 344 | - #21 NameAnonymousFunctions + outlineJSX stub (380 lines) |
| 345 | - #22 OutlineFunctions (162 lines) |
| 346 | - #23 AlignMethodCallScopes (183 lines) |
| 347 | - #24 AlignObjectMethodScopes (205 lines) |
| 348 | - #25 PruneUnusedLabelsHIR (108 lines) |
| 349 | - #26 AlignReactiveScopesToBlockScopesHIR (782 lines) — biggest jump: 73→1243 passed |
| 350 | - #27 MergeOverlappingReactiveScopesHIR (789 lines) |
| 351 | - #28 BuildReactiveScopeTerminalsHIR (736 lines) — 1243→1392 passed |
| 352 | - #29 FlattenReactiveLoopsHIR (70 lines) |
| 353 | - #30 FlattenScopesWithHooksOrUseHIR (156 lines) |
| 354 | - #31 PropagateScopeDependenciesHIR (2382 lines) — the final HIR pass |
| 355 | Overall: 1342/1717 passing (78%). 375 failures from pre-existing upstream diffs. |
| 356 | Next pass is #32 BuildReactiveFunction — BLOCKED, needs test infra extension. |
| 357 | |
| 358 | ## 20260320-133636 Fix remaining failures: 375→80 |
| 359 | |
| 360 | Fixed 295 of 375 failures across multiple passes: |
| 361 | - VED pipeline guard: always run VED (TS 'off' is truthy). Fixed 58 failures. |
| 362 | - OutlineFunctions: debug printer includes outlined function bodies, UID naming |
| 363 | convention matches Babel, depth-first name allocation ordering. Fixed ~125. |
| 364 | - Validation passes ported: ValidateNoSetStateInRender, ValidateExhaustiveDependencies, |
| 365 | ValidateNoJSXInTryStatement, ValidateNoSetStateInEffects. Fixed ~40. |
| 366 | - PropagateScopeDependenciesHIR: BTreeSet determinism, inner function hoistable |
| 367 | property loads, propagation result fix, deferred dependency check. Fixed ~30. |
| 368 | - ANALYSIS.md issues: globals.rs callee effects, infer_types fresh names map, |
| 369 | RewriteInstructionKinds Phase 2 ordering + invariant restoration. Fixed ~10. |
| 370 | - Test harness: normalizeIds reset at function boundaries. Fixed ~15. |
| 371 | Remaining 80 failures: RIKBR (23, VED false positive cascade), PSDH (20), |
| 372 | ValidateNoSetStateInRender (13), OutlineFunctions (9), InferReactivePlaces (7), |
| 373 | MergeOverlapping (3), others (5). |
| 374 | Overall: 1637/1717 passing (95.3%). |
| 375 | |
| 376 | ## 20260320-141021 Port validateNoDerivedComputationsInEffects_exp |
| 377 | |
| 378 | Ported the experimental validateNoDerivedComputationsInEffects_exp validation pass |
| 379 | from TypeScript to Rust. The 13 "ValidateNoSetStateInRender" failures were actually |
| 380 | caused by this unported pass — the test harness misattributed them to the preceding pass. |
| 381 | Created validate_no_derived_computations_in_effects.rs (1269 lines) in react_compiler_validation. |
| 382 | Overall: 1650/1717 passing (96.1%), 67 failures remaining. |
| 383 | |
| 384 | ## 20260320-161141 Fix ValidateNoSetStateInEffects — port createControlDominators |
| 385 | |
| 386 | Ported createControlDominators / isRefControlledBlock logic from ControlDominators.ts |
| 387 | into validate_no_set_state_in_effects.rs. Added post-dominator frontier computation |
| 388 | and phi-node predecessor block fallback. Fixes 1 failure (valid-setState-in-useEffect-controlled-by-ref-value.js). |
| 389 | Overall: 1651/1717 passing (96.2%), 66 failures remaining. |
| 390 | |
| 391 | ## 20260320-171654 Fix upstream validation passes — 7 InferReactivePlaces failures resolved |
| 392 | |
| 393 | Fixed 3 validation passes causing 7 failures misattributed to InferReactivePlaces: |
| 394 | - ValidateNoRefAccessInRender: hook kind detection via env lookup instead of shape_id matching, |
| 395 | added missing else branch for useState/useReducer, fixed joinRefAccessRefTypes semantics. |
| 396 | - ValidateLocalsNotReassignedAfterRender: added LoadContext propagation, noAlias check for |
| 397 | Array callback methods to eliminate false positives. |
| 398 | - Ported non-experimental ValidateNoDerivedComputationsInEffects (replacing TODO stub). |
| 399 | Overall: 1658/1717 passing (96.6%), 59 failures remaining. |
| 400 | |
| 401 | ## 20260320-201055 Fix multiple passes — 1658→1673 (+15 tests) |
| 402 | |
| 403 | Three categories of fixes: |
| 404 | - ObjectExpression computed key operand ordering: fixed in 4 files (infer_reactive_places, |
| 405 | infer_mutation_aliasing_effects, merge_overlapping_reactive_scopes, propagate_scope_deps). |
| 406 | TS yields computed key before value; Rust had them reversed. Fixed 10 PSDH + 5 RIKBR. |
| 407 | - Port ValidateStaticComponents: new validation pass detecting dynamically-created components. |
| 408 | Fixed 5 static-components/invalid-* fixtures. |
| 409 | - Port reduceMaybeOptionalChains in PropagateScopeDependenciesHIR: reduces optional chains |
| 410 | when base is known non-null. Fixed 3 fixtures. |
| 411 | - RIKBR error format: fixed Some(Reassign) → Reassign, added place detail string. |
| 412 | Overall: 1673/1717 passing (97.4%), 44 failures remaining. |
| 413 | |
| 414 | ## 20260320-213855 Fix VED, PSDH, AlignObjectMethod — 1673→1695 (+22) |
| 415 | |
| 416 | Removed VED error stripping (was hiding 18 legitimate errors) after fixing VED false |
| 417 | positives via correct StartMemoize/FinishMemoize scoping of dependency collection. |
| 418 | Fixed PSDH inner function traversal for nested FunctionExpressions. Fixed |
| 419 | AlignObjectMethodScopes scope range accumulation (HashMap for min/max). |
| 420 | Overall: 1695/1717 passing (98.7%), 22 failures remaining. |
| 421 | |
| 422 | ## 20260321-000048 Fix PSDH assumed-invoked functions and outline_jsx — 1695→1700 (+5) |
| 423 | |
| 424 | Fixed PSDH get_assumed_invoked_functions to share temporaries map across inner function |
| 425 | recursion. Fixed outline_jsx: aliasingEffects Some(vec![]) instead of None, IndexMap for |
| 426 | prop ordering, skip all JSX instructions in outlined groups. |
| 427 | Overall: 1700/1717 passing (99.0%), 17 failures remaining. |
| 428 | |
| 429 | ## 20260321-000048 Fix OutlineFunctions and MergeOverlappingReactiveScopesHIR — 1700→1709 (+9) |
| 430 | |
| 431 | Fixed outline_jsx block rewrite to place replacement at LAST JSX position (matching TS |
| 432 | reverse iteration). Fixed MergeOverlappingReactiveScopesHIR scope deduplication to preserve |
| 433 | insertion order instead of sorting by ScopeId. All OutlineFunctions and MergeOverlapping |
| 434 | passes now clean. Remaining 8 failures: PSDH scope declarations (5), error reporting from |
| 435 | unported reactive passes (3). |
| 436 | Overall: 1709/1717 passing (99.5%), 8 failures remaining. |
| 437 | |
| 438 | ## 20260321-010000 Fix PropagateScopeDependenciesHIR — 1709→1713 (+4) |
| 439 | |
| 440 | Fixed two bugs in PSDH: |
| 441 | - ProcessedInstr key collision: used IdentifierId instead of EvaluationOrder (not unique |
| 442 | across functions), fixing 3 scope declaration failures + 2 ASIWS cascades. |
| 443 | - Iterative non-null propagation fails on loops: replaced with recursive DFS using |
| 444 | active/done state tracking (matching TS recursivelyPropagateNonNull). |
| 445 | All 4 remaining failures are blocked on unported reactive passes or error handling. |
| 446 | Overall: 1713/1717 passing (99.8%), 4 failures remaining. |
| 447 | |
| 448 | ## 20260320-213806 Port all reactive passes after BuildReactiveFunction |
| 449 | |
| 450 | Ported 15 reactive passes + visitor infrastructure from TypeScript to Rust: |
| 451 | - Visitor/transform traits (visitors.rs) with closure-based traversal |
| 452 | - assertWellFormedBreakTargets, pruneUnusedLabels, assertScopeInstructionsWithinScopes |
| 453 | - pruneNonEscapingScopes (1123 lines), pruneNonReactiveDependencies, pruneUnusedScopes |
| 454 | - mergeReactiveScopesThatInvalidateTogether, pruneAlwaysInvalidatingScopes, propagateEarlyReturns |
| 455 | - pruneUnusedLValues, promoteUsedTemporaries, extractScopeDeclarationsFromDestructuring |
| 456 | - stabilizeBlockIds, renameVariables, pruneHoistedContexts |
| 457 | Fixed RenameVariables value-level lvalue visiting and inner function traversal (154 failures fixed). |
| 458 | Fixed PruneNonReactiveDependencies inner function context visiting (23 failures fixed). |
| 459 | |
| 460 | ## 20260323-130614 Fix RenameVariables, ExtractScopeDeclarations, PruneNonEscapingScopes — 36→13 failures |
| 461 | |
| 462 | Fixed 23 test failures across three passes: |
| 463 | - RenameVariables: PrunedScope scoping fix (visit_block_inner for pruned scopes, matching TS |
| 464 | traverseBlock vs visitBlock), plus addNewReference registration in pipeline.rs. 16→2 failures. |
| 465 | - ExtractScopeDeclarationsFromDestructuring: Fixed temporary place metadata — copy type from |
| 466 | original identifier, preserve source location on identifier, use GeneratedSource for Place loc. 8→0 failures. |
| 467 | - PruneNonEscapingScopes: Added FunctionExpression/ObjectMethod context operands from |
| 468 | env.functions for captured variable tracking. 1→0 failures. |
| 469 | Overall: 1704/1717 passing (99.2%), 13 failures remaining. |
| 470 | |
| 471 | ## 20260323-160933 Fix 11 failures, add Result support to ReactiveFunctionTransform |
| 472 | |
| 473 | Fixed 11 test failures (13→2 remaining): |
| 474 | - MergeReactiveScopesThatInvalidateTogether: propagate parent_deps through terminals, |
| 475 | add lvalue tracking in FindLastUsage. 6→0 failures. |
| 476 | - Error message formatting: formatLoc treats null as (generated), invariant error details |
| 477 | in RIKBR, BuildReactiveFunction error format fix. 5→0 failures. |
| 478 | - PruneHoistedContexts: return Err() for Todo errors instead of state workaround. |
| 479 | |
| 480 | Refactored ReactiveFunctionTransform trait to return Result<..., CompilerError> on all |
| 481 | methods, enabling proper error propagation. Removed all .unwrap() calls on |
| 482 | transform_reactive_function — callers propagate with ?. |
| 483 | Overall: 1715/1717 passing (99.9%), 2 failures remaining (block ID ordering). |
| 484 | |
| 485 | ## 20260323-201154 Implement apply_compiled_functions — codegen application |
| 486 | |
| 487 | Implemented the full codegen application pipeline so the Rust compiler now produces |
| 488 | actual compiled JavaScript output instead of returning the original source: |
| 489 | - compile_result.rs: Added id, params, body, generator, is_async fields to CodegenFunction |
| 490 | - pipeline.rs: Pass through AST fields from codegen result |
| 491 | - program.rs: Full apply_compiled_functions implementation — finds functions by BaseNode.start, |
| 492 | replaces params/body, inserts outlined functions, renames useMemoCache, adds imports |
| 493 | - codegen_reactive_function.rs: All BaseNode::default() → BaseNode::typed("...") for proper |
| 494 | JSON serialization of AST node types |
| 495 | - common.rs: Added BaseNode::typed() constructor |
| 496 | - BabelPlugin.ts: Replaced prog.replaceWith() with pass.file.ast.program assignment, |
| 497 | added comment deduplication for JSON round-trip reference sharing |
| 498 | - imports.rs: BaseNode::typed() for import-related AST nodes |
| 499 | Pass tests: 1715/1717 (2 flaky, pass individually). Code tests: 1586/1717 (92.4%). |
| 500 | Remaining 131 code failures: error handling differences (67), codegen output (23), |
| 501 | gating features (21), outlined ordering (12), other (8). |
| 502 | |
| 503 | ## 20260324-210207 Fix outlined ordering, type annotations, script source type — 130→110 code failures |
| 504 | |
| 505 | Fixed three categories of code comparison failures: |
| 506 | - Outlined function ordering: changed from reverse to forward iteration in apply_compiled_functions, |
| 507 | matching Babel's insertAfter behavior. Fixed 12 failures. |
| 508 | - Type annotation preservation: added type_annotation field to TypeCastExpression in HIR, |
| 509 | populated during lowering for TSAsExpression/TSSatisfiesExpression/TSTypeAssertion/FlowTypeCast, |
| 510 | emitted in codegen as proper AST wrapper nodes. Fixed 6 failures. |
| 511 | - Script source type: implemented require() syntax for CJS modules in imports.rs using |
| 512 | VariableDeclaration with ObjectPattern destructuring + require() CallExpression. Fixed 1 failure. |
| 513 | Code comparison: 1586→1607 passing (93.6%). 110 remaining. |
| 514 | |
| 515 | ## 20260324-214542 Implement gating codegen — 110→96 code failures |
| 516 | |
| 517 | Implemented function gating for the Rust compiler port: |
| 518 | - Standard gating: wraps compiled functions in `gating() ? compiled : original` conditional |
| 519 | - Hoisted gating: creates dispatcher function for functions referenced before declaration |
| 520 | - Dynamic gating: supports `'use memo if(identifier)'` directive with @dynamicGating config |
| 521 | - Export handling: export default/named function gating patterns |
| 522 | - Import sorting: case-insensitive to match JS localeCompare behavior |
| 523 | 17 gating fixtures fixed (21/29 gating tests passing). 8 remaining are function discovery, |
| 524 | error handling paths, and unimplemented instrumentation features. |
| 525 | Code comparison: 1607→1621 passing (94.4%). 96 remaining. |
| 526 | |
| 527 | ## 20260324-233646 Port ValidatePreservedManualMemoization — 96→38 code failures |
| 528 | |
| 529 | Ported ValidatePreservedManualMemoization from TypeScript to Rust (~440 lines). |
| 530 | Validates that compiled output preserves manual useMemo/useCallback memoization: |
| 531 | - StartMemoize operand scope checks (dependency scope must complete before memo block) |
| 532 | - FinishMemoize unmemoized value detection (values must be within reactive scopes) |
| 533 | - Scope dependency matching (inferred deps must match manually specified deps) |
| 534 | Replaced TODO stub in pipeline.rs with real validation pass call. |
| 535 | Fixed 58 code comparison failures. Code: 1621→1679 (97.8%). 38 remaining. |
| 536 | |
| 537 | ## 20260325-011107 Fix error handling, enum passthrough, codegen invariants — 38→30 code failures |
| 538 | |
| 539 | Fixed 8 code comparison failures: |
| 540 | - Enum declarations: preserve original AST node through codegen instead of __unsupported_* placeholder |
| 541 | - throwUnknownException__testonly: pipeline support for test-only exception pragma |
| 542 | - MethodCall invariant: codegen checks property resolves to MemberExpression |
| 543 | - Unnamed temporary invariant: convert_identifier returns Result, errors on unnamed temps |
| 544 | - Const/Let declaration invariant: cannot have outer lvalue (expression reference) |
| 545 | - useMemo-switch-return: fixed as side effect (was flaky, now passes consistently) |
| 546 | Code: 1679→1687 (98.3%). 30 remaining. |
| 547 | |
| 548 | ## 20260325-123533 Fix JSX outlining, function discovery, gating — 32→14 code failures |
| 549 | |
| 550 | Two parallel fixes: |
| 551 | 1. JSX outlining: re-compile outlined functions through full pipeline (create fresh Environment, |
| 552 | build synthetic AST, lower to HIR, run all passes). All 9 jsx-outlining-* fixtures pass. |
| 553 | 2. Function discovery: add ExpressionStatement + deep expression recursion to AST replacement/ |
| 554 | gating/rename traversals. Fix infer mode for React.memo/forwardRef, nested arrows in |
| 555 | exports, gating edge cases. |
| 556 | Commits: 526eced507 (function discovery), plus outstanding environment.rs changes. |
| 557 | Code: 1687→1703 (99.2%). 14 remaining. |
| 558 | |
| 559 | ## 20260325-145443 Fix all remaining failures — 1717/1717 pass + code (100%) |
| 560 | |
| 561 | Fixed final 14 code failures + 1 pass-level failure: |
| 562 | - Instrumentation: enableEmitInstrumentForget codegen (3 fixtures), enableEmitHookGuards |
| 563 | with per-hook-call try/finally wrapping (1 fixture) |
| 564 | - Dynamic gating: fixed error handling to use handle_error (3 fixtures) |
| 565 | - StabilizeBlockIds: IndexSet for deterministic iteration, fixing dominator.js + useMemo-inverted-if |
| 566 | - Fast refresh: enableResetCacheOnSourceFileChanges with HMAC-SHA256 hash codegen (1 fixture) |
| 567 | - Reserved words: Babel plugin throws on scope extraction failure with panicThreshold (1 fixture) |
| 568 | - Source locations: run full pipeline before recording Todo error (1 fixture) |
| 569 | - Variable renaming: surface BindingRename from HIR to BabelPlugin for scope.rename() (2 fixtures) |
| 570 | - Use-no-forget: add memo cache import before error check in pipeline (1 fixture) |
| 571 | ALL TESTS PASSING: Pass 1717/1717, Code 1717/1717. |
| 572 | |
| 573 | ## 20260328-235900 Remove local visitor copies — use canonical react_compiler_hir::visitors |
| 574 | |
| 575 | Replaced ~1,800 lines of duplicated visitor/iterator match logic across 21 files with |
| 576 | calls to canonical `react_compiler_hir::visitors` functions. Remaining local functions are |
| 577 | thin wrappers (e.g., calling canonical and mapping `Place` → `IdentifierId`). |
| 578 | Added `each_instruction_value_operand_with_functions` to canonical visitors for split-borrow cases. |
| 579 | All 1717 tests still passing. Pass 1717/1717, Code 1717/1717. |
| 580 | |
| 581 | ## 20260330-134202 Fix 30 snap test failures — validation, codegen, prefilter |
| 582 | |
| 583 | Fixed 30 snap test failures across multiple categories: |
| 584 | - ValidatePreservedManualMemoization: added has_invalid_deps flag to suppress spurious errors (7 fixed) |
| 585 | - Type provider validation: fixed error messages, added namespace import validation (3 fixed) |
| 586 | - knownIncompatible: implemented IncompatibleLibrary error check with early return (3 fixed) |
| 587 | - JSON log ordering: added CompileErrorWithLoc variant, fixed severity with logged_severity() (2 fixed) |
| 588 | - Code-frame abbreviation: ported CODEFRAME_MAX_LINES logic to Rust BabelPlugin.ts (2 fixed) |
| 589 | - Codegen error formatting: for-init messages, MethodCall span narrowing, for-in/of locs (4 fixed) |
| 590 | - Error message text: "this is Const" format matching TS (1 fixed) |
| 591 | - Prefilter: React.memo/forwardRef detection in TS and SWC prefilters (3 fixed) |
| 592 | - globals.rs: toString() on BuiltInObject/MixedReadonly, is_ref_like_name fix (3 fixed) |
| 593 | - scope.rs/hir_builder.rs: name-based binding fallback for component-syntax ref params (1 fixed) |
| 594 | - Snap runner: auto-enable sync mode when --rust is set (1 infra fix) |
| 595 | Pass 1717/1717, Code 1717/1717, Snap 1702/1718. |
| 596 | |
| 597 | ## 20260330-145244 Fix remaining snap failures — 1717/1718 (99.9%) |
| 598 | |
| 599 | Fixed 10 more snap test failures: |
| 600 | - FBT loc propagation (8 fixed): Added loc to convert_identifier, codegen_place, make_var_declarator, |
| 601 | codegen_jsx_attribute, and instruction value expressions in codegen_reactive_function.rs. |
| 602 | - identifierName in diagnostics (1 fixed): Enhanced get_identifier_name_with_loc in |
| 603 | validate_no_derived_computations_in_effects.rs with fallback to declaration_id and source extraction. |
| 604 | - Component/hook declaration syntax (2 fixed): Added __componentDeclaration and __hookDeclaration |
| 605 | boolean fields to FunctionDeclaration AST, updated program.rs to detect these in function discovery. |
| 606 | - BuiltInMixedReadonly methods (2 fixed): Added 13 missing methods (indexOf, includes, at, map, |
| 607 | flatMap, filter, concat, slice, every, some, find, findIndex, join) to globals.rs. |
| 608 | - idx-no-outlining (1 fixed): Normalize unused _refN declarations in snap reporter. |
| 609 | - ValidateSourceLocations: silently skip in Rust (pipeline.rs). |
| 610 | Pass 1717/1717, Code 1716/1717, Snap 1717/1718. Only remaining: error.todo-missing-source-locations (intentional). |
| 611 | |
| 612 | ## 20260331-220427 Port OptimizeForSSR pass |
| 613 | |
| 614 | Ported OptimizeForSSR (#13) from TypeScript to Rust. The pass optimizes components for |
| 615 | SSR by inlining useState/useReducer, removing effects and event handlers, and stripping |
| 616 | known event handler/ref props from builtin JSX. Gated on outputMode === 'ssr'. |
| 617 | Created optimize_for_ssr.rs in react_compiler_optimization crate. Added is_plain_object_type |
| 618 | and is_start_transition_type helpers to react_compiler_hir. |
| 619 | test-rust-port: 1724/1724, Snap --rust: 1725/1725. |
| 620 | |
| 621 | ## 20260402-103329 Fix e2e diagnostic event mismatches — 123→2 failures |
| 622 | |
| 623 | Fixed 121 of 123 babel e2e test failures (diagnostic events only, no code changes): |
| 624 | - Description field: removed skip_serializing_if on `description` and `message` fields |
| 625 | in CompilerErrorDetailInfo, ensuring `null` is always serialized (70 fixtures). |
| 626 | - Diagnostic suggestions: added LoggerSuggestionInfo struct with LoggerSuggestionOp enum |
| 627 | (InsertBefore=0, InsertAfter=1, Remove=2, Replace=3), ported suggestion generation from |
| 628 | TS. Implemented exhaustive deps suggestion generation in validate_exhaustive_dependencies (23 fixtures). |
| 629 | - record_error Result type: Environment::record_error() now returns Result<(), CompilerError>, |
| 630 | returning Err for Invariant category. All callers use `?` for short-circuit propagation. |
| 631 | - CompileUnexpectedThrow events: Added emission in process_fn when CompilerError has is_thrown |
| 632 | flag, matching TS tryCompileFunction behavior (5 fixtures). |
| 633 | - Invariant error format: Changed invariant errors to use CompilerDiagnostic with details array |
| 634 | (matching TS CompilerError.invariant() format) in codegen_reactive_function (5 fixtures). |
| 635 | - JSX outlining events: Emit CompileSuccess for outlined functions with fn_type.is_some() after |
| 636 | main compilation loop, matching TS queue ordering (9 fixtures). |
| 637 | - Empty suggestions: Fixed `Some(vec![])` vs `None` for empty suggestion arrays (2 fixtures). |
| 638 | Remaining 2: handle-unexpected-exception (PipelineError stack trace), todo-kitchensink (index field). |
| 639 | test-rust-port: 1724/1724, e2e babel: 1722/1724, swc: 1584/1724, oxc: 688/1724. |
| 640 | |
| 641 | ## 20260401-105521 Move error formatting to Rust, fix JSXAttribute loc in codegen |
| 642 | |
| 643 | Moved error formatting from JS to Rust: added code_frame.rs to react_compiler_diagnostics |
| 644 | with code frame rendering and format_compiler_error(). Rust now returns pre-formatted error |
| 645 | messages via formatted_message field on CompilerErrorInfo, eliminating ~160 lines of JS |
| 646 | formatting code (formatCompilerError, categoryToHeading, printCodeFrame) and the @babel/code-frame |
| 647 | dependency from babel-plugin-react-compiler-rust. Also fixed JSXExpressionContainer nodes in |
| 648 | codegen to propagate source locations from place.loc, eliminating the ensureNodeLocs JS post-pass. |
| 649 | test-rust-port: 1724/1724, Snap: 1725/1725, Snap --rust: 1725/1725. |