delete cdp session from cache on page close

This commit is contained in:
Tommy D. Rossi
2026-02-03 18:35:07 +01:00
parent 0a38084263
commit d401b22dfe
2 changed files with 66 additions and 1 deletions
+18 -1
View File
@@ -610,12 +610,29 @@ export class PlaywrightExecutor {
}
const getCDPSession = async (options: { page: Page }) => {
if (options.page.isClosed()) {
throw new Error('Cannot create CDP session for closed page')
}
const cached = this.cdpSessionCache.get(options.page)
if (cached) return cached
if (cached) {
return cached
}
// Generate a fresh unique URL for each CDP session to avoid client ID conflicts
const wsUrl = getCdpUrl(this.cdpConfig)
const session = await getCDPSessionForPage({ page: options.page, wsUrl })
this.cdpSessionCache.set(options.page, session)
options.page.on('close', () => {
const cachedSession = this.cdpSessionCache.get(options.page)
if (!cachedSession) {
return
}
this.cdpSessionCache.delete(options.page)
cachedSession.close()
})
return session
}
+48
View File
@@ -5,6 +5,7 @@ import { getCdpUrl } from './utils.js'
import { getCDPSessionForPage } from './cdp-session.js'
import { Debugger } from './debugger.js'
import { Editor } from './editor.js'
import { PlaywrightExecutor } from './executor.js'
import { setupTestContext, cleanupTestContext, getExtensionServiceWorker, createSseServer, safeCloseCDPBrowser, type TestContext, withTimeout, js } from './test-utils.js'
import './test-declarations.js'
@@ -106,6 +107,53 @@ describe('CDP Session Tests', () => {
await page.close()
}, 60000)
it('should reuse cached CDP session and close on page close', async () => {
const browserContext = getBrowserContext()
const serviceWorker = await getExtensionServiceWorker(browserContext)
const page = await browserContext.newPage()
await page.goto('https://example.com/')
await page.bringToFront()
await serviceWorker.evaluate(async () => {
await globalThis.toggleExtensionForActiveTab()
})
await new Promise(r => setTimeout(r, 100))
const executor = new PlaywrightExecutor({
cdpConfig: { port: TEST_PORT },
logger: {
log: () => {},
error: () => {},
},
})
const result = await executor.execute(js`
const sessionA = await getCDPSession({ page })
const sessionB = await getCDPSession({ page })
await sessionA.send('Runtime.evaluate', { expression: '1 + 1', returnByValue: true })
const evalResult = await sessionB.send('Runtime.evaluate', { expression: '2 + 2', returnByValue: true })
return evalResult.result.value
`)
expect(result.isError).toBe(false)
expect(result.text).toContain('[return value] 4')
await page.close()
const closeResult = await executor.execute(js`
try {
const session = await getCDPSession({ page })
await session.send('Runtime.evaluate', { expression: '3 + 3', returnByValue: true })
return 'unexpected'
} catch (e) {
return 'closed'
}
`)
expect(closeResult.isError).toBe(false)
expect(closeResult.text).toContain('[return value] closed')
}, 60000)
it('should list scripts with Debugger class', async () => {
const browserContext = getBrowserContext()
const serviceWorker = await getExtensionServiceWorker(browserContext)