mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-05 15:47:57 +02:00
fix(browse): clear refs when iframe auto-detaches in getActiveFrameOrPage
Asymmetric cleanup between two equivalent staleness conditions:
onMainFrameNavigated() → clearRefs() + activeFrame = null ✓
getActiveFrameOrPage() → activeFrame = null (refs NOT cleared) ✗
Both paths see the same staleness condition — refs were captured
against a frame that no longer exists. The main-frame path correctly
clears both pieces of state. The iframe-detach path nulls the frame
but leaves the refMap intact.
The lazy click-time check in `resolveRef` (tab-session.ts:97) partially
saves us — `entry.locator.count()` on a detached-frame locator throws
or returns 0, so the click errors out as "Ref X is stale". But the
user has no signal that frame context silently changed underfoot: the
next `snapshot` runs against `this.page` (main) while old iframe refs
still litter `refMap` with the same role+name keys. New refs collide
with stale ones, the resolver picks one at random, the user clicks
the wrong element.
TODOS.md line 816-820 documents "Detached frame auto-recovery" as a
shipped iframe-support feature in v0.12.1.0. This restores the
documented intent — the recovery should leave the session in a clean
state, not a half-cleared one.
Fix: 1 line — add `this.clearRefs()` next to `this.activeFrame = null`
inside the if-branch.
Test plan:
- [x] New regression test: 4/4 pass
- refs cleared when getActiveFrameOrPage detects detached iframe
- refs preserved when active frame is still attached (no regression)
- refs preserved when no frame set (page-level path untouched)
- matches onMainFrameNavigated symmetry — both paths reach the
same clean end state
- [x] `bun run build` clean
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -149,9 +149,16 @@ export class TabSession {
|
||||
* Use this for operations that work on both Page and Frame (locator, evaluate, etc.).
|
||||
*/
|
||||
getActiveFrameOrPage(): Page | Frame {
|
||||
// Auto-recover from detached frames (iframe removed/navigated)
|
||||
// Auto-recover from detached frames (iframe removed/navigated). Clear
|
||||
// refs alongside the activeFrame — same staleness condition as
|
||||
// onMainFrameNavigated() below: refs were captured against a frame
|
||||
// that no longer exists. Without this, refMap entries linger against
|
||||
// a dead frame after silently falling back to the main page; the
|
||||
// next snapshot's role+name keys collide with stale entries and the
|
||||
// resolver picks one at random.
|
||||
if (this.activeFrame?.isDetached()) {
|
||||
this.activeFrame = null;
|
||||
this.clearRefs();
|
||||
}
|
||||
return this.activeFrame ?? this.page;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user