diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/autonomous_completion.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/autonomous_completion.rs index 74ddebcf9..5900681f4 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/autonomous_completion.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/autonomous_completion.rs @@ -4591,8 +4591,12 @@ fn javascript_apply_alias_transition( return; } if transition.conditional { + let had_state = state.resolved; state.indices.extend(transition.indices); state.resolved = true; + if !had_state { + state.conditional = true; + } } else { *state = transition; } @@ -9582,6 +9586,19 @@ mod javascript_projection_reachability_tests { assert!(javascript_position_is_reachable(content, &ranges, decoy)); } + #[test] + fn conditional_assignment_inside_an_invoked_function_preserves_prior_state() { + let content = "const real = { run() { return import('./real.mjs'); } }; const decoy = { run() { return import('./decoy.mjs'); } }; let receiver = real; function maybeSwap() { if (flag) receiver = decoy; } maybeSwap(); function start() { return receiver.run(); } start();"; + let ranges = named_javascript_function_ranges(content); + for source in ["./real.mjs", "./decoy.mjs"] { + let position = content.find(source).expect("find conditional callee owner"); + assert!( + javascript_position_is_reachable(content, &ranges, position), + "a conditional callee side effect must preserve both states: {source}", + ); + } + } + #[test] fn super_owner_is_fixed_when_the_class_is_defined() { let content = "let Base = class { run() { return import('./real-base.mjs'); } }; class Game extends Base { start() { return super.run(); } } Base = class { run() { return import('./decoy-base.mjs'); } }; new Game().start();";