fix(tauri): reset the frame context when switching windows - #559
Conversation
Split out of #532, which fixes this as a side effect of child-webview support. The bug is independent of that feature and present on main today. `switch_to_window` set `current_window` and left `frame_context` untouched. W3C Switch To Window selects the target window's *top-level* browsing context, but because the stack survived, `wrap_script_for_frame_context` kept wrapping every subsequent command to descend `doc.querySelectorAll('iframe, frame')[i]` — so after switching out of a frame, scripts and element lookups in the new window walked into whatever sat at that index there. Nothing in the tauri e2e suite exercises switchToFrame, which is why it went unnoticed. `Session::switch_to_window` now advances a browsing-context generation and clears the frame stack in one step, and frame commits are validated against that generation: a switch landing during the executor's frame validation no longer pushes a frame onto the wrong window. Also refreshes the stale fixture Cargo.lock (it still pinned the plugin crates at 1.0.0 while their manifests say 1.2.0, so any fixture build dirtied it). Co-authored-by: abu0306 <abu0306@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CsgeivZCqduTQmWK55zqiT
|
| Filename | Overview |
|---|---|
| packages/tauri-plugin-webdriver/src/server/handlers/frame.rs | Adds generation- and window-lifetime-checked frame commits around asynchronous frame operations, with unit coverage for each mutation. |
| packages/tauri-plugin-webdriver/src/webdriver/session.rs | Centralizes window switching so the selected window, cleared frame stack, and browsing-context generation update together. |
| packages/tauri-plugin-webdriver/src/server/handlers/window.rs | Routes successful window switches through the new atomic session operation and maps the theoretical generation overflow. |
| packages/tauri-plugin-webdriver/src/server/mod.rs | Adds a window-registry predicate used to reject delayed frame commits after their original window closes. |
| fixtures/e2e-apps/tauri/Cargo.lock | Synchronizes the two local Tauri WDIO package versions with their manifests without changing third-party dependency versions. |
Sequence Diagram
sequenceDiagram
participant Client
participant FrameHandler
participant Session
participant WindowHandler
Client->>FrameHandler: switchToFrame request
FrameHandler->>Session: Snapshot window, frame stack, generation
FrameHandler->>FrameHandler: Validate frame asynchronously
Client->>WindowHandler: switchToWindow
WindowHandler->>Session: Set window, clear frames, increment generation
FrameHandler->>Session: Commit using captured generation
Session-->>FrameHandler: Reject changed browsing context
Reviews (1): Last reviewed commit: "fix(tauri): reset the frame context when..." | Re-trigger Greptile
|
Standing release PR: #456 · 15 packages queued · open 39d 1h 47m · ✅ ready to merge Release Preview — 17 packages
These changes will be added to the release PR (#456) when merged: Changelog@wdio/dioxus-bridge 1.0.0-next.3 → 1.0.0-next.4
@wdio/dioxus-service 1.0.0-next.3 → 1.0.0-next.4
wdio-dioxus-driver 1.0.0-next.3 → 1.0.0-next.4
wdio-dioxus-embedded-driver 1.0.0-next.3 → 1.0.0-next.4
@wdio/tauri-plugin 1.2.0 → 1.2.1
@wdio/tauri-service 1.2.0 → 1.2.1
tauri-plugin-wdio-webdriver 1.2.0 → 1.2.1
@wdio/flutter-service 1.0.0-next.1 → 1.0.0-next.2
wdio_flutter N/A → 0.1.1
@wdio/electrobun-service 0.1.0 → 0.1.1
@wdio/electron-service 10.1.0 → 10.1.1
@wdio/native-cdp-bridge 1.0.0 → 1.0.1
@wdio/native-core 1.0.0 → 1.0.1
@wdio/native-mobile-core 1.0.0 → 1.0.1
@wdio/native-spy 1.1.0 → 1.1.1
@wdio/native-types 2.4.0 → 2.4.1
@wdio/native-utils 2.5.0 → 2.5.1
@wdio/react-native-service 1.0.0-next.0 → 1.0.0-next.1
After merge — predicted release
Updated automatically by ReleaseKit |
Two more #540 DirectEval idle-stalls (`Error: Script execution timed out`, embedded provider, WebKit macOS): - #560 run 30701420535 — Package - Tauri [macOS-ARM] - #559 run 30701283449 — E2E - Tauri [macOS-ARM] - deeplink (also the app-unreachable variant: `failed to send request … "window" GET`) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKc4JHZKXfyqCiiU4C2b7V
More #540 DirectEval idle-stalls (`Script execution timed out` / app-unreachable `failed to send request … "window" GET`, embedded provider, WebKit macOS): - #560 run 30701420535 — Package - Tauri [macOS-ARM] - #559 run 30701283449 — E2E - Tauri [macOS-ARM] - deeplink; both attempt 1 and the attempt-2 retry failed F1 (retry did not clear it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKc4JHZKXfyqCiiU4C2b7V
…acOS) More #540 DirectEval idle-stalls (`Script execution timed out` / app-unreachable `failed to send request … "window" GET`, embedded provider, WebKit macOS): - #560 run 30701420535 — Package - Tauri [macOS-ARM] - #559 run 30701283449 — E2E - Tauri [macOS-ARM] - deeplink failed F1 on all THREE attempts; retry never cleared it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKc4JHZKXfyqCiiU4C2b7V
…acOS) More #540 DirectEval idle-stalls (`Script execution timed out` / app-unreachable `failed to send request … "window" GET`, embedded provider, WebKit macOS): - #560 run 30701420535 — Package - Tauri [macOS-ARM] - #559 run 30701283449 — E2E - Tauri [macOS-ARM] - deeplink failed F1 on all THREE attempts; retry never cleared it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKc4JHZKXfyqCiiU4C2b7V
…#540) (#563) More #540 DirectEval idle-stalls (`Script execution timed out` / app-unreachable `failed to send request … "window" GET`, embedded provider, WebKit macOS): - #560 run 30701420535 — Package - Tauri [macOS-ARM] - #559 run 30701283449 — E2E - Tauri [macOS-ARM] - deeplink failed F1 on all THREE attempts; retry never cleared it. Claude-Session: https://claude.ai/code/session_01CKc4JHZKXfyqCiiU4C2b7V Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Description
Split out of #532, with attribution to @abu0306 — that PR fixes this as a side effect of child-webview support, but the bug is independent of the feature and present on
maintoday.The bug
switch_to_windowupdates the current window and leaves the frame stack alone:W3C Switch To Window selects the target window's top-level browsing context. Because the stack survives,
wrap_script_for_frame_contextkeeps wrapping every later command to descenddoc.querySelectorAll('iframe, frame')[i]once per stack entry — so afterswitchToWindow(B)while inside a frame of A, scripts and element lookups in B walk into whatever happens to sit at that index in B. Wrong content, or an error.Nothing in the tauri e2e suite calls
switchToFrame(grepreturns nothing), which is why this has gone unnoticed.The fix
Session::switch_to_windowadvances a browsing-context generation and clears the frame stack in one step, and frame commits are validated against that generation before they are applied. That also closes a TOCTOU:switch_to_framevalidates via the executor across anawait, and a concurrent window switch landing in that window previously pushed a frame onto the wrong window.Adapted from #532 in one respect —
has_window_labelis implemented over the stablewebview_windows()rather than theunstable-gatedwebviews(), so this carries none of that PR's Tauri feature requirements.Also refreshes the stale fixture
Cargo.lock: it still pinnedtauri-plugin-wdio/tauri-plugin-wdio-webdriverat1.0.0while their manifests say1.2.0, so any fixture build left the tree dirty. Bundled here rather than as a third PR since it comes from the same source.Deliberately left in #532
The
no_such_windowguard onget_window_handleand everything child-webview specific.Type of Change
Scope
scope:tauri- Tauri service and pluginTesting
cargo test— 23 passed (up from 15): 6 newcommit_frame_contextcases and 2 newswitch_to_windowcasescargo clippy --all-targets -- -D warnings— clean, modulo the two pre-existing violations onmainthat ci(rust): run clippy on the first-party Rust crates #557 fixesrustfmt --edition 2021 --check— clean on both changed Rust files🤖 Generated with Claude Code
https://claude.ai/code/session_01CsgeivZCqduTQmWK55zqiT