Skip to content

Commit 0b9ad2b

Browse files
authored
perf(screencast): clean cdp frame listeners on stop (#671)
1 parent 069f14d commit 0b9ad2b

2 files changed

Lines changed: 56 additions & 5 deletions

File tree

packages/screencast/src/index.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,35 @@
33
module.exports = (page, opts) => {
44
const cdp = page._client()
55
let onFrame
6+
let hasFrameListener = false
67

7-
cdp.on('Page.screencastFrame', ({ data, metadata, sessionId }) => {
8+
const onScreencastFrame = ({ data, metadata, sessionId }) => {
89
cdp.send('Page.screencastFrameAck', { sessionId }).catch(() => {})
9-
if (metadata.timestamp) onFrame(data, metadata)
10-
})
10+
if (metadata.timestamp && onFrame) onFrame(data, metadata)
11+
}
12+
13+
const attachFrameListener = () => {
14+
if (hasFrameListener) return
15+
cdp.on('Page.screencastFrame', onScreencastFrame)
16+
hasFrameListener = true
17+
}
18+
19+
const detachFrameListener = () => {
20+
if (!hasFrameListener) return
21+
cdp.off('Page.screencastFrame', onScreencastFrame)
22+
hasFrameListener = false
23+
}
1124

1225
return {
1326
// https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-startScreencast
14-
start: () => cdp.send('Page.startScreencast', opts),
27+
start: () => {
28+
attachFrameListener()
29+
return cdp.send('Page.startScreencast', opts)
30+
},
1531
onFrame: fn => (onFrame = fn),
16-
stop: () => cdp.send('Page.stopScreencast').catch(() => {})
32+
stop: () => {
33+
detachFrameListener()
34+
return cdp.send('Page.stopScreencast').catch(() => {})
35+
}
1736
}
1837
}

packages/screencast/test/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,35 @@ test('capture frames', async t => {
3131
t.truthy(metadata.timestamp)
3232
})
3333
})
34+
35+
test('clean up cdp frame listeners across screencast sessions', async t => {
36+
const browserless = await getBrowserContext(t)
37+
const page = await browserless.page()
38+
const cdp = page._client()
39+
40+
const countListeners = () => cdp.listenerCount('Page.screencastFrame')
41+
42+
const screencastA = createScreencast(page, {
43+
quality: 0,
44+
format: 'png',
45+
everyNthFrame: 1
46+
})
47+
48+
t.is(countListeners(), 0)
49+
50+
await screencastA.start()
51+
t.is(countListeners(), 1)
52+
await screencastA.stop()
53+
t.is(countListeners(), 0)
54+
55+
const screencastB = createScreencast(page, {
56+
quality: 0,
57+
format: 'png',
58+
everyNthFrame: 1
59+
})
60+
61+
await screencastB.start()
62+
t.is(countListeners(), 1)
63+
await screencastB.stop()
64+
t.is(countListeners(), 0)
65+
})

0 commit comments

Comments
 (0)