mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-18 10:52:24 +02:00
fix(browse): capture active-tab state before close() — last-tab auto-create raced the close event
closeTab checked `tabId === this.activeTabId` AFTER awaiting page.close(), but the page 'close' event handler can fire during that await and reassign activeTabId — losing the race meant the last-tab auto-create never ran, leaving the manager with zero tabs. Capture wasActive before closing, and only reassign activeTabId when it no longer points at a live tab. Part of the test-integrity repairs unmasked by the suite-truncation fix. Contributed by @time-attack (PR #2230, browser-manager hunk). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f77bbe7091
commit
3aab765417
@@ -798,19 +798,31 @@ export class BrowserManager {
|
|||||||
const page = this.pages.get(tabId);
|
const page = this.pages.get(tabId);
|
||||||
if (!page) throw new Error(`Tab ${tabId} not found`);
|
if (!page) throw new Error(`Tab ${tabId} not found`);
|
||||||
|
|
||||||
|
// Capture BEFORE close(): the page 'close' event handler wired in
|
||||||
|
// wirePageEvents() can fire while page.close() is awaited. It removes
|
||||||
|
// the tab from the maps and reassigns activeTabId (to 0 when no tabs
|
||||||
|
// remain), so a post-close `tabId === this.activeTabId` check is
|
||||||
|
// order-dependent — whether the event dispatches before or after
|
||||||
|
// close() resolves varies across Playwright/Chromium versions and
|
||||||
|
// machines, and losing the race means the last-tab auto-create below
|
||||||
|
// never runs, leaving the manager with zero tabs.
|
||||||
|
const wasActive = tabId === this.activeTabId;
|
||||||
|
|
||||||
await page.close();
|
await page.close();
|
||||||
this.pages.delete(tabId);
|
this.pages.delete(tabId);
|
||||||
this.tabSessions.delete(tabId);
|
this.tabSessions.delete(tabId);
|
||||||
this.tabOwnership.delete(tabId);
|
this.tabOwnership.delete(tabId);
|
||||||
|
|
||||||
// Switch to another tab if we closed the active one
|
// Switch to another tab if we closed the active one
|
||||||
if (tabId === this.activeTabId) {
|
if (wasActive) {
|
||||||
const remaining = [...this.pages.keys()];
|
const remaining = [...this.pages.keys()];
|
||||||
if (remaining.length > 0) {
|
if (remaining.length === 0) {
|
||||||
this.activeTabId = remaining[remaining.length - 1];
|
|
||||||
} else {
|
|
||||||
// No tabs left — create a new blank one
|
// No tabs left — create a new blank one
|
||||||
await this.newTab();
|
await this.newTab();
|
||||||
|
} else if (!this.pages.has(this.activeTabId)) {
|
||||||
|
// The 'close' handler may have already switched to a valid tab;
|
||||||
|
// only reassign when activeTabId no longer points at a live tab.
|
||||||
|
this.activeTabId = remaining[remaining.length - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user