* Capture browser state: cookies, localStorage, sessionStorage, URLs, active tab. * Skips pages that fail storage reads (e.g., already closed).
()
| 1264 | * Skips pages that fail storage reads (e.g., already closed). |
| 1265 | */ |
| 1266 | async saveState(): Promise<BrowserState> { |
| 1267 | if (!this.context) throw new Error('Browser not launched'); |
| 1268 | |
| 1269 | const cookies = await this.context.cookies(); |
| 1270 | const pages: BrowserState['pages'] = []; |
| 1271 | |
| 1272 | for (const [id, page] of this.pages) { |
| 1273 | const url = page.url(); |
| 1274 | let storage = null; |
| 1275 | try { |
| 1276 | storage = await page.evaluate(() => ({ |
| 1277 | localStorage: { ...localStorage }, |
| 1278 | sessionStorage: { ...sessionStorage }, |
| 1279 | })); |
| 1280 | } catch {} |
| 1281 | |
| 1282 | // Capture load-html content so a later context recreation (viewport --scale) |
| 1283 | // can replay it via setTabContent. Never persisted to disk. |
| 1284 | const session = this.tabSessions.get(id); |
| 1285 | const loaded = session?.getLoadedHtml(); |
| 1286 | // Preserve tab ownership through recreation so scoped agents aren't locked out. |
| 1287 | const owner = this.tabOwnership.get(id); |
| 1288 | |
| 1289 | pages.push({ |
| 1290 | url: url === 'about:blank' ? '' : url, |
| 1291 | isActive: id === this.activeTabId, |
| 1292 | storage, |
| 1293 | loadedHtml: loaded?.html, |
| 1294 | loadedHtmlWaitUntil: loaded?.waitUntil, |
| 1295 | owner, |
| 1296 | }); |
| 1297 | } |
| 1298 | |
| 1299 | return { cookies, pages }; |
| 1300 | } |
| 1301 | |
| 1302 | /** |
| 1303 | * Restore browser state into the current context: cookies, pages, storage. |
no test coverage detected