browserless 14.1.2 → 14.1.4
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/index.d.ts +4 -1
- package/package.json +5 -5
- package/src/index.js +28 -17
package/index.d.ts
CHANGED
|
@@ -40,7 +40,10 @@ export interface Context {
|
|
|
40
40
|
text: (url: string, opts?: GotoOptions) => Promise<string>
|
|
41
41
|
getDevice: (deviceName: string) => Viewport | undefined
|
|
42
42
|
report: (opts?: { benchmark?: boolean }) => Promise<HardwareInfo>
|
|
43
|
-
destroyContext: (opts?: {
|
|
43
|
+
destroyContext: (opts?: {
|
|
44
|
+
/** @deprecated A destroyed context never retries, so `force` has no effect. */
|
|
45
|
+
force?: boolean
|
|
46
|
+
}) => Promise<void>
|
|
44
47
|
withPage: <T>(fn: (page: Page, goto: unknown) => Promise<T>, opts?: { timeout?: number, keepPage?: boolean }) => Promise<T>
|
|
45
48
|
}
|
|
46
49
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "browserless",
|
|
3
3
|
"description": "The headless Chrome/Chromium driver on top of Puppeteer. Take screenshots, generate PDFs, extract text and HTML with a production-ready API.",
|
|
4
4
|
"homepage": "https://browserless.js.org",
|
|
5
|
-
"version": "14.1.
|
|
5
|
+
"version": "14.1.4",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"main": "src/index.js",
|
|
8
8
|
"author": {
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@browserless/errors": "14.0.22",
|
|
39
|
-
"@browserless/goto": "14.1.
|
|
40
|
-
"@browserless/pdf": "14.1.
|
|
41
|
-
"@browserless/screenshot": "14.1.
|
|
39
|
+
"@browserless/goto": "14.1.4",
|
|
40
|
+
"@browserless/pdf": "14.1.4",
|
|
41
|
+
"@browserless/screenshot": "14.1.4",
|
|
42
42
|
"debug-logfmt": "~1.4.15",
|
|
43
43
|
"kill-process-group": "~1.0.16",
|
|
44
44
|
"p-reflect": "~2.1.0",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"timeout": "2m",
|
|
71
71
|
"workerThreads": false
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "136b2d9f50772f096aa81af66780c1b625ec2fc1"
|
|
74
74
|
}
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { ensureError, browserTimeout } = require('@browserless/errors')
|
|
3
|
+
const { ensureError, browserTimeout, contextDisconnected } = require('@browserless/errors')
|
|
4
4
|
const createScreenshot = require('@browserless/screenshot')
|
|
5
5
|
const debug = require('debug-logfmt')('browserless')
|
|
6
6
|
const createGoto = require('@browserless/goto')
|
|
@@ -111,18 +111,23 @@ module.exports = ({ timeout: globalTimeout = 30000, ...launchOpts } = {}) => {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
const createContext = async ({ retry = 2, timeout: contextTimeout, ...contextOpts } = {}) => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
let forwardedContextOpts
|
|
115
|
+
const forwardContextOpts = () => {
|
|
116
|
+
forwardedContextOpts = isClosed
|
|
117
|
+
? Promise.resolve(contextOpts)
|
|
118
|
+
: forwardProxy(contextOpts, { mode: launchOpts.mode })
|
|
119
|
+
forwarders.add(forwardedContextOpts)
|
|
120
|
+
return forwardedContextOpts
|
|
121
|
+
}
|
|
122
|
+
const newBrowserContext = () =>
|
|
123
|
+
(forwardedContextOpts ?? forwardContextOpts()).then(createBrowserContext)
|
|
120
124
|
let _contextPromise = newBrowserContext()
|
|
121
|
-
let isDestroyedForced = false
|
|
122
125
|
let isDestroyed = false
|
|
123
126
|
const pageMetadata = new WeakMap()
|
|
127
|
+
const isAbandoned = () => isClosed || isDestroyed
|
|
124
128
|
|
|
125
|
-
const getBrowserContext = () =>
|
|
129
|
+
const getBrowserContext = () =>
|
|
130
|
+
isDestroyed ? Promise.reject(contextDisconnected()) : _contextPromise
|
|
126
131
|
|
|
127
132
|
const createPage = async name => {
|
|
128
133
|
const duration = debug.duration('createPage')
|
|
@@ -172,9 +177,11 @@ module.exports = ({ timeout: globalTimeout = 30000, ...launchOpts } = {}) => {
|
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
try {
|
|
180
|
+
if (isAbandoned()) throw contextDisconnected()
|
|
175
181
|
page = await createPage(name)
|
|
176
182
|
closePageTimeout = startCloseTimeout()
|
|
177
183
|
const value = await fn(page, goto)(...args)
|
|
184
|
+
if (isAbandoned()) throw contextDisconnected()
|
|
178
185
|
// A timeout already rejected the caller, who never received this
|
|
179
186
|
// page. Retaining it would clear the in-call watchdog and arm a
|
|
180
187
|
// new one with nobody holding the page.
|
|
@@ -200,11 +207,11 @@ module.exports = ({ timeout: globalTimeout = 30000, ...launchOpts } = {}) => {
|
|
|
200
207
|
onFailedAttempt: async error => {
|
|
201
208
|
debug('onFailedAttempt', { name: error.name, code: error.code, isRejected })
|
|
202
209
|
if (error.name === 'AbortError') throw error
|
|
203
|
-
if (isRejected
|
|
210
|
+
if (isRejected) throw new AbortError()
|
|
204
211
|
const isRetryable =
|
|
205
212
|
error.code === 'EBRWSRCONTEXTCONNRESET' || error.code === 'EPROTOCOL'
|
|
206
213
|
if (!isRetryable) throw error
|
|
207
|
-
if (
|
|
214
|
+
if (isAbandoned()) throw new AbortError()
|
|
208
215
|
const { message, attemptNumber, retriesLeft } = error
|
|
209
216
|
// Every attempt builds its own page, so both codes are retryable
|
|
210
217
|
// inside the existing context: `EBRWSRCONTEXTCONNRESET` covers a
|
|
@@ -247,20 +254,24 @@ module.exports = ({ timeout: globalTimeout = 30000, ...launchOpts } = {}) => {
|
|
|
247
254
|
)
|
|
248
255
|
}
|
|
249
256
|
|
|
250
|
-
const destroyContext = async (
|
|
257
|
+
const destroyContext = async () => {
|
|
251
258
|
isDestroyed = true
|
|
252
|
-
|
|
259
|
+
const closingContextPromise = _contextPromise
|
|
260
|
+
const closingContextOpts = forwardedContextOpts
|
|
261
|
+
_contextPromise = undefined
|
|
262
|
+
forwardedContextOpts = undefined
|
|
263
|
+
if (!closingContextPromise) return
|
|
253
264
|
|
|
254
265
|
try {
|
|
255
266
|
const [browserProcess, browserContext] = await Promise.all([
|
|
256
267
|
getBrowser(),
|
|
257
|
-
|
|
268
|
+
closingContextPromise
|
|
258
269
|
])
|
|
259
270
|
await pReflect(browserContext.close())
|
|
260
|
-
debug('destroyContext', { pid: driver.pid(browserProcess),
|
|
271
|
+
debug('destroyContext', { pid: driver.pid(browserProcess), id: browserContext.id })
|
|
261
272
|
} finally {
|
|
262
|
-
forwarders.delete(
|
|
263
|
-
await closeForwarder(
|
|
273
|
+
forwarders.delete(closingContextOpts)
|
|
274
|
+
await closeForwarder(closingContextOpts)
|
|
264
275
|
}
|
|
265
276
|
}
|
|
266
277
|
|