@browserless/screenshot 13.9.1 → 13.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/index.js +10 -3
- package/src/is-transient-context-loss.js +17 -0
- package/src/wait-for-ready.js +2 -2
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@browserless/screenshot",
|
|
3
3
|
"description": "Capture high-quality screenshots of websites with overlay support, device emulation, and automated image optimization.",
|
|
4
4
|
"homepage": "https://browserless.js.org/#/?id=screenshoturl-options",
|
|
5
|
-
"version": "13.9.
|
|
5
|
+
"version": "13.9.5",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"author": {
|
|
8
8
|
"email": "hello@microlink.io",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@browserless/errors": "13.6.10",
|
|
36
|
-
"@browserless/goto": "13.9.
|
|
36
|
+
"@browserless/goto": "13.9.5",
|
|
37
37
|
"@kikobeats/content-type": "~1.0.4",
|
|
38
38
|
"@kikobeats/time-span": "~1.0.12",
|
|
39
39
|
"automad-prism-themes": "~0.3.7",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"timeout": "2m",
|
|
71
71
|
"workerThreads": false
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "a82ea003023e3131498bec74ed51761dfd6d6615"
|
|
74
74
|
}
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const debug = require('debug-logfmt')('browserless:screenshot')
|
|
4
|
-
const { isContextDestroyed } = require('@browserless/errors')
|
|
5
4
|
const createGoto = require('@browserless/goto')
|
|
6
5
|
const { extname } = require('node:path')
|
|
7
6
|
const pReflect = require('p-reflect')
|
|
8
7
|
|
|
8
|
+
const isTransientContextLoss = require('./is-transient-context-loss')
|
|
9
9
|
const isWhiteScreenshot = require('./is-white-screenshot')
|
|
10
10
|
const waitForPrism = require('./pretty')
|
|
11
11
|
const prettyTimeSpan = require('./time-span')
|
|
@@ -22,15 +22,22 @@ const {
|
|
|
22
22
|
|
|
23
23
|
const timeSpan = require('@kikobeats/time-span')()
|
|
24
24
|
|
|
25
|
+
// No pacing here on purpose: `waitUntilAuto` is a network-idle wait, which on a
|
|
26
|
+
// live page costs at least its idle window (~500ms) and at most what is left of
|
|
27
|
+
// the budget. The runaway case was never a fast loop — it was retrying a page
|
|
28
|
+
// that was gone, where the wait returns instantly. Classify that and the loop
|
|
29
|
+
// paces itself on real work.
|
|
25
30
|
const captureWithNavigationRetry = async (capture, { page, goto, timeout }) => {
|
|
26
31
|
const elapsed = timeSpan()
|
|
32
|
+
const remaining = () => timeout - elapsed()
|
|
27
33
|
while (true) {
|
|
28
34
|
try {
|
|
29
35
|
return await capture()
|
|
30
36
|
} catch (error) {
|
|
31
|
-
if (!
|
|
37
|
+
if (!isTransientContextLoss(page, error) || remaining() <= 0) throw error
|
|
32
38
|
debug('captureWithNavigationRetry', { error: error.message })
|
|
33
|
-
await goto.waitUntilAuto(page, { timeout })
|
|
39
|
+
await goto.waitUntilAuto(page, { timeout: remaining() })
|
|
40
|
+
if (remaining() <= 0) throw error
|
|
34
41
|
}
|
|
35
42
|
}
|
|
36
43
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { isContextDestroyed } = require('@browserless/errors')
|
|
4
|
+
|
|
5
|
+
// Tells a frame torn down mid-flight (a client-side navigation, which settles
|
|
6
|
+
// and retries fine) apart from a page we no longer have: once the page or its
|
|
7
|
+
// session is closed — the request ended and its context was destroyed — nothing
|
|
8
|
+
// it is waiting on can arrive, so waiting is spent on work nobody wants.
|
|
9
|
+
//
|
|
10
|
+
// `TargetCloseError` is puppeteer's own signal that the CDP session is detached
|
|
11
|
+
// (`CdpSession.send` raises it the moment `detached` is set). Ask it as well as
|
|
12
|
+
// the page: the session flips first, so between the two there is a window where
|
|
13
|
+
// every call throws yet `isClosed()` still answers false.
|
|
14
|
+
const isTransientContextLoss = (page, error) =>
|
|
15
|
+
isContextDestroyed(error) && error?.name !== 'TargetCloseError' && !page.isClosed()
|
|
16
|
+
|
|
17
|
+
module.exports = isTransientContextLoss
|
package/src/wait-for-ready.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { setTimeout: sleep } = require('node:timers/promises')
|
|
4
|
-
const
|
|
4
|
+
const isTransientContextLoss = require('./is-transient-context-loss')
|
|
5
5
|
|
|
6
6
|
const DEFAULT_QUIET_MS = 300
|
|
7
7
|
const DEFAULT_POLL_MS = 150
|
|
@@ -193,7 +193,7 @@ const waitForReady = async (
|
|
|
193
193
|
try {
|
|
194
194
|
signals = await page.evaluate(paintSignals)
|
|
195
195
|
} catch (error) {
|
|
196
|
-
if (!
|
|
196
|
+
if (!isTransientContextLoss(page, error)) throw error
|
|
197
197
|
resets++
|
|
198
198
|
lastHeight = -1
|
|
199
199
|
quietSince = 0
|