From c24381bff90621c3a4ffb7e71e61b925a3b46a9a Mon Sep 17 00:00:00 2001 From: Amit <3540115+amitdeshmukh@users.noreply.github.com> Date: Wed, 16 Apr 2025 23:38:06 +0530 Subject: [PATCH 1/4] feat: add persistent browser context handling - Add _persistentContext property to store and reuse browser context - Cache and reuse existing persistent context if available - Improve browser context management efficiency --- src/context.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/context.ts b/src/context.ts index a0fd4d69..cac624ef 100644 --- a/src/context.ts +++ b/src/context.ts @@ -162,10 +162,18 @@ export class Context { return { browserContext }; } + private _persistentContext: playwright.BrowserContext | null = null; + private async _launchPersistentContext(): Promise { + // If we already have a persistent context, return it. + if (this._persistentContext) { + return this._persistentContext; + } + // Otherwise, launch a new persistent context. try { const browserType = this.options.browserName ? playwright[this.options.browserName] : playwright.chromium; - return await browserType.launchPersistentContext(this.options.userDataDir, this.options.launchOptions); + this._persistentContext = await browserType.launchPersistentContext(this.options.userDataDir, this.options.launchOptions); + return this._persistentContext; } catch (error: any) { if (error.message.includes('Executable doesn\'t exist')) throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`); From 730736b75cc3526920f952274c396ccc383a3a24 Mon Sep 17 00:00:00 2001 From: Amit <3540115+amitdeshmukh@users.noreply.github.com> Date: Thu, 17 Apr 2025 14:13:12 +0530 Subject: [PATCH 2/4] refactor(context): improve browser context lifecycle management - Consolidate persistent context handling into _ensureBrowserContext - Optimize cleanup by running context/browser closures in parallel - Only set persistent context for local browser instances - Move _persistentContext property with other context properties This change simplifies the browser context management code while maintaining the same functionality, making it more maintainable and efficient. --- src/context.ts | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/context.ts b/src/context.ts index cac624ef..5be50c94 100644 --- a/src/context.ts +++ b/src/context.ts @@ -40,6 +40,7 @@ export class Context { readonly options: ContextOptions; private _browser: playwright.Browser | undefined; private _browserContext: playwright.BrowserContext | undefined; + private _persistentContext: playwright.BrowserContext | null = null; private _tabs: Tab[] = []; private _currentTab: Tab | undefined; @@ -120,19 +121,31 @@ export class Context { return; const browserContext = this._browserContext; const browser = this._browser; + const persistentContext = this._persistentContext; + this._browserContext = undefined; this._browser = undefined; + this._persistentContext = null; - await browserContext?.close().then(async () => { - await browser?.close(); - }).catch(() => {}); + await Promise.all([ + browserContext?.close(), + browser?.close(), + persistentContext?.close() + ]).catch(() => {}); } private async _ensureBrowserContext() { if (!this._browserContext) { - const context = await this._createBrowserContext(); - this._browser = context.browser; - this._browserContext = context.browserContext; + if (this._persistentContext) { + this._browserContext = this._persistentContext; + } else { + const context = await this._createBrowserContext(); + this._browser = context.browser; + this._browserContext = context.browserContext; + if (!this.options.remoteEndpoint && !this.options.cdpEndpoint) { + this._persistentContext = this._browserContext; + } + } for (const page of this._browserContext.pages()) this._onPageCreated(page); this._browserContext.on('page', page => this._onPageCreated(page)); @@ -158,22 +171,10 @@ export class Context { return { browser, browserContext }; } - const browserContext = await this._launchPersistentContext(); - return { browserContext }; - } - - private _persistentContext: playwright.BrowserContext | null = null; - - private async _launchPersistentContext(): Promise { - // If we already have a persistent context, return it. - if (this._persistentContext) { - return this._persistentContext; - } - // Otherwise, launch a new persistent context. try { const browserType = this.options.browserName ? playwright[this.options.browserName] : playwright.chromium; - this._persistentContext = await browserType.launchPersistentContext(this.options.userDataDir, this.options.launchOptions); - return this._persistentContext; + const browserContext = await browserType.launchPersistentContext(this.options.userDataDir, this.options.launchOptions); + return { browserContext }; } catch (error: any) { if (error.message.includes('Executable doesn\'t exist')) throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`); From c7aee7e6d2613780eee3201c606eab7d4dfb1ed9 Mon Sep 17 00:00:00 2001 From: Amit <3540115+amitdeshmukh@users.noreply.github.com> Date: Fri, 18 Apr 2025 00:00:02 +0530 Subject: [PATCH 3/4] fix: linter errors --- src/context.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/context.ts b/src/context.ts index f03e6e03..7d684289 100644 --- a/src/context.ts +++ b/src/context.ts @@ -217,7 +217,6 @@ ${code.join('\n')} const browserContext = this._browserContext; const browser = this._browser; const persistentContext = this._persistentContext; - this._browserContext = undefined; this._browser = undefined; this._persistentContext = null; @@ -237,9 +236,8 @@ ${code.join('\n')} const context = await this._createBrowserContext(); this._browser = context.browser; this._browserContext = context.browserContext; - if (!this.options.remoteEndpoint && !this.options.cdpEndpoint) { + if (!this.options.remoteEndpoint && !this.options.cdpEndpoint) this._persistentContext = this._browserContext; - } } for (const page of this._browserContext.pages()) this._onPageCreated(page); From d1e5be2f345af11549bd96a7c842fb1cbb4dbda9 Mon Sep 17 00:00:00 2001 From: Amit <3540115+amitdeshmukh@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:58:28 +0530 Subject: [PATCH 4/4] Remove emitGeneric option from ariaSnapshot call --- src/context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.ts b/src/context.ts index 0d96c18c..b0db3cf5 100644 --- a/src/context.ts +++ b/src/context.ts @@ -420,7 +420,7 @@ class PageSnapshot { private async _snapshotFrame(frame: playwright.Page | playwright.FrameLocator) { const frameIndex = this._frameLocators.push(frame) - 1; - const snapshotString = await frame.locator('body').ariaSnapshot({ ref: true, emitGeneric: true }); + const snapshotString = await frame.locator('body').ariaSnapshot({ ref: true }); const snapshot = yaml.parseDocument(snapshotString); const visit = async (node: any): Promise => {