delete cdp session from cache on page close
This commit is contained in:
@@ -610,12 +610,29 @@ export class PlaywrightExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getCDPSession = async (options: { page: Page }) => {
|
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)
|
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
|
// Generate a fresh unique URL for each CDP session to avoid client ID conflicts
|
||||||
const wsUrl = getCdpUrl(this.cdpConfig)
|
const wsUrl = getCdpUrl(this.cdpConfig)
|
||||||
const session = await getCDPSessionForPage({ page: options.page, wsUrl })
|
const session = await getCDPSessionForPage({ page: options.page, wsUrl })
|
||||||
this.cdpSessionCache.set(options.page, session)
|
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
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { getCdpUrl } from './utils.js'
|
|||||||
import { getCDPSessionForPage } from './cdp-session.js'
|
import { getCDPSessionForPage } from './cdp-session.js'
|
||||||
import { Debugger } from './debugger.js'
|
import { Debugger } from './debugger.js'
|
||||||
import { Editor } from './editor.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 { setupTestContext, cleanupTestContext, getExtensionServiceWorker, createSseServer, safeCloseCDPBrowser, type TestContext, withTimeout, js } from './test-utils.js'
|
||||||
import './test-declarations.js'
|
import './test-declarations.js'
|
||||||
|
|
||||||
@@ -106,6 +107,53 @@ describe('CDP Session Tests', () => {
|
|||||||
await page.close()
|
await page.close()
|
||||||
}, 60000)
|
}, 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 () => {
|
it('should list scripts with Debugger class', async () => {
|
||||||
const browserContext = getBrowserContext()
|
const browserContext = getBrowserContext()
|
||||||
const serviceWorker = await getExtensionServiceWorker(browserContext)
|
const serviceWorker = await getExtensionServiceWorker(browserContext)
|
||||||
|
|||||||
Reference in New Issue
Block a user