@browserless/goto 9.1.6 → 9.2.19

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@browserless/goto",
3
3
  "description": "Go to a page aborting unnecessary requests",
4
4
  "homepage": "https://browserless.js.org/#/?id=gotopage-options",
5
- "version": "9.1.6",
5
+ "version": "9.2.19",
6
6
  "main": "src/index.js",
7
7
  "author": {
8
8
  "email": "hello@microlink.io",
@@ -30,7 +30,7 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@browserless/devices": "^9.1.6",
33
- "@cliqz/adblocker-puppeteer": "~1.22.2",
33
+ "@cliqz/adblocker-puppeteer": "~1.22.7",
34
34
  "debug-logfmt": "~1.0.4",
35
35
  "got": "~11.8.2",
36
36
  "is-url-http": "~2.2.4",
@@ -39,7 +39,7 @@
39
39
  "pretty-ms": "~7.0.1",
40
40
  "shallow-equal": "~1.2.1",
41
41
  "time-span": "~4.0.0",
42
- "top-user-agents": "~1.0.29",
42
+ "top-user-agents": "~1.0.38",
43
43
  "tough-cookie": "~4.0.0",
44
44
  "unique-random-array": "~2.0.0"
45
45
  },
@@ -68,5 +68,5 @@
68
68
  "timeout": "2m",
69
69
  "verbose": true
70
70
  },
71
- "gitHead": "3ea16a0beb3aacbae2679a494322829074590783"
71
+ "gitHead": "e44bfcf5f5ead8f42ad758c200b8fc5c1be4a761"
72
72
  }
package/src/engine.bin CHANGED
Binary file
package/src/index.js CHANGED
@@ -29,15 +29,14 @@ const isEmpty = val => val == null || !(Object.keys(val) || val).length
29
29
 
30
30
  const castArray = value => [].concat(value).filter(Boolean)
31
31
 
32
- const getInjectKey = (ext, value) =>
33
- isUrl(value) ? 'url' : value.endsWith(`.${ext}`) ? 'path' : 'content'
34
-
35
- const injectCSS = (page, css) =>
36
- pReflect(
37
- page.addStyleTag({
38
- content: css
39
- })
40
- )
32
+ const run = async ({ fn, timeout, debug: props }) => {
33
+ const debugProps = { duration: timeSpan() }
34
+ const result = await pReflect(pTimeout(fn, timeout))
35
+ debugProps.duration = prettyMs(debugProps.duration())
36
+ if (result.isRejected) debugProps.error = result.reason.message || result.reason
37
+ debug(props, debugProps)
38
+ return result
39
+ }
41
40
 
42
41
  const parseCookies = (url, str) =>
43
42
  str.split(';').reduce((acc, cookieStr) => {
@@ -66,28 +65,19 @@ const getMediaFeatures = ({ animations, colorScheme }) => {
66
65
  return prefers
67
66
  }
68
67
 
69
- const injectScripts = (page, values, attributes) =>
70
- Promise.all(
71
- castArray(values).map(value =>
72
- pReflect(
73
- page.addScriptTag({
74
- [getInjectKey('js', value)]: value,
75
- ...attributes
76
- })
77
- )
78
- )
79
- )
68
+ const injectScript = (page, value, attributes) =>
69
+ page.addScriptTag({
70
+ [getInjectKey('js', value)]: value,
71
+ ...attributes
72
+ })
80
73
 
81
- const injectStyles = (page, styles) =>
82
- Promise.all(
83
- castArray(styles).map(style =>
84
- pReflect(
85
- page.addStyleTag({
86
- [getInjectKey('css', style)]: style
87
- })
88
- )
89
- )
90
- )
74
+ const injectStyle = (page, style) =>
75
+ page.addStyleTag({
76
+ [getInjectKey('css', style)]: style
77
+ })
78
+
79
+ const getInjectKey = (ext, value) =>
80
+ isUrl(value) ? 'url' : value.endsWith(`.${ext}`) ? 'path' : 'content'
91
81
 
92
82
  const disableAnimations = `
93
83
  *,
@@ -101,29 +91,22 @@ const disableAnimations = `
101
91
  }
102
92
  `.trim()
103
93
 
104
- const run = async ({ fn, debug: props }) => {
105
- const debugProps = { duration: timeSpan() }
106
- const result = await pReflect(fn)
107
- debugProps.duration = prettyMs(debugProps.duration())
108
- if (result.isRejected) debugProps.error = result.reason.message || result.reason
109
- debug(props, debugProps)
110
- return result
111
- }
112
-
113
94
  // related https://github.com/puppeteer/puppeteer/issues/1353
114
95
  const createWaitUntilAuto = defaultOpts => (page, opts) => {
115
96
  const { timeout } = { ...defaultOpts, ...opts }
116
97
 
117
- return run({
118
- fn: pTimeout(
119
- Promise.all([
120
- page.waitForNavigation({ waitUntil: 'networkidle2' }),
121
- page.evaluate(() => window.history.pushState(null, null, null))
122
- ]),
123
- timeout * (1 / 8)
124
- ),
125
- debug: { isWaitUntilAuto: true }
126
- })
98
+ return Promise.all(
99
+ [
100
+ {
101
+ fn: () => page.waitForNavigation({ waitUntil: 'networkidle2' }),
102
+ debug: 'waitUntilAuto:waitForNavigation'
103
+ },
104
+ {
105
+ fn: () => page.evaluate(() => window.history.pushState(null, null, null)),
106
+ debug: 'waitUntilAuto:pushState'
107
+ }
108
+ ].map(({ fn, ...opts }) => run({ fn: fn(), timeout, ...opts }))
109
+ )
127
110
  }
128
111
 
129
112
  module.exports = ({
@@ -133,18 +116,17 @@ module.exports = ({
133
116
  ...deviceOpts
134
117
  }) => {
135
118
  const baseTimeout = globalTimeout * (1 / 2)
119
+ const actionTimeout = baseTimeout * (1 / 8)
120
+
136
121
  const getDevice = createDevices(deviceOpts)
137
122
  const { viewport: defaultViewport } = getDevice.findDevice(defaultDevice)
138
123
 
139
- const applyEvasions = castArray(evasions)
140
- .filter(Boolean)
141
- .reduce((acc, key) => [...acc, EVASIONS[key]], [])
142
-
143
- const _waitUntilAuto = createWaitUntilAuto({ timeout: baseTimeout })
124
+ const _waitUntilAuto = createWaitUntilAuto({ timeout: actionTimeout })
144
125
 
145
126
  const goto = async (
146
127
  page,
147
128
  {
129
+ abortTypes = [],
148
130
  adblock = true,
149
131
  animations = false,
150
132
  click,
@@ -162,10 +144,10 @@ module.exports = ({
162
144
  timeout = baseTimeout,
163
145
  timezone,
164
146
  url,
147
+ waitForFunction,
165
148
  waitForSelector,
166
149
  waitForTimeout,
167
150
  waitForXPath,
168
- waitForFunction,
169
151
  waitUntil = 'auto',
170
152
  waitUntilAuto = _waitUntilAuto,
171
153
  ...args
@@ -177,13 +159,20 @@ module.exports = ({
177
159
  const prePromises = []
178
160
 
179
161
  if (adblock) {
180
- prePromises.push(engine.enableBlockingInPage(page))
162
+ prePromises.push(
163
+ run({
164
+ fn: engine.enableBlockingInPage(page),
165
+ timeout: actionTimeout,
166
+ debug: 'adblock'
167
+ })
168
+ )
181
169
  }
182
170
 
183
171
  if (javascript === false) {
184
172
  prePromises.push(
185
173
  run({
186
174
  fn: page.setJavaScriptEnabled(false),
175
+ timeout: actionTimeout,
187
176
  debug: { javascript }
188
177
  })
189
178
  )
@@ -199,6 +188,7 @@ module.exports = ({
199
188
  prePromises.push(
200
189
  run({
201
190
  fn: page.setViewport(device.viewport),
191
+ timeout: actionTimeout,
202
192
  debug: 'viewport'
203
193
  })
204
194
  )
@@ -212,6 +202,7 @@ module.exports = ({
212
202
  prePromises.push(
213
203
  run({
214
204
  fn: page.setCookie(...cookies),
205
+ timeout: actionTimeout,
215
206
  debug: ['cookies', ...cookies.map(({ name }) => name)]
216
207
  })
217
208
  )
@@ -221,6 +212,7 @@ module.exports = ({
221
212
  prePromises.push(
222
213
  run({
223
214
  fn: page.setUserAgent(headers['user-agent']),
215
+ timeout: actionTimeout,
224
216
  debug: { 'user-agent': headers['user-agent'] }
225
217
  })
226
218
  )
@@ -229,6 +221,7 @@ module.exports = ({
229
221
  prePromises.push(
230
222
  run({
231
223
  fn: page.setExtraHTTPHeaders(headers),
224
+ timeout: actionTimeout,
232
225
  debug: { headers: headersKeys }
233
226
  })
234
227
  )
@@ -238,6 +231,7 @@ module.exports = ({
238
231
  prePromises.push(
239
232
  run({
240
233
  fn: page.emulateMediaType(mediaType),
234
+ timeout: actionTimeout,
241
235
  debug: { mediaType }
242
236
  })
243
237
  )
@@ -247,6 +241,7 @@ module.exports = ({
247
241
  prePromises.push(
248
242
  run({
249
243
  fn: page.emulateTimezone(timezone),
244
+ timeout: actionTimeout,
250
245
  debug: { timezone }
251
246
  })
252
247
  )
@@ -258,15 +253,37 @@ module.exports = ({
258
253
  prePromises.push(
259
254
  run({
260
255
  fn: page.emulateMediaFeatures(mediaFeatures),
261
- debug: { mediaFeatures: mediaFeatures.length }
256
+ timeout: actionTimeout,
257
+ debug: { mediaFeatures: mediaFeatures.map(({ name }) => name) }
262
258
  })
263
259
  )
264
260
  }
265
261
 
266
- await Promise.all(prePromises.concat(applyEvasions.map(fn => fn(page))))
262
+ const applyEvasions = castArray(evasions)
263
+ .filter(Boolean)
264
+ .map(key =>
265
+ run({
266
+ fn: EVASIONS[key](page),
267
+ timeout: actionTimeout,
268
+ debug: key
269
+ })
270
+ )
271
+
272
+ await Promise.all(prePromises.concat(applyEvasions))
273
+
274
+ if (abortTypes.length > 0) {
275
+ await page.setRequestInterception(true)
276
+ page.on('request', req => {
277
+ const resourceType = req.resourceType()
278
+ if (!abortTypes.includes(resourceType)) return req.continue()
279
+ debug('abort', { url: req.url(), resourceType })
280
+ return req.abort('blockedbyclient')
281
+ })
282
+ }
267
283
 
268
284
  const { value } = await run({
269
- fn: pTimeout(html ? page.setContent(html, args) : page.goto(url, args), timeout),
285
+ fn: html ? page.setContent(html, args) : page.goto(url, args),
286
+ timeout,
270
287
  debug: html ? 'html' : 'url'
271
288
  })
272
289
 
@@ -276,40 +293,71 @@ module.exports = ({
276
293
  waitForFunction,
277
294
  waitForTimeout
278
295
  })) {
279
- if (value) await run({ fn: page[key](value), debug: { [key]: value } })
296
+ if (value) {
297
+ await run({ fn: page[key](value), timeout: actionTimeout, debug: { [key]: value } })
298
+ }
280
299
  }
281
300
 
282
301
  const postPromises = []
283
302
 
284
303
  if (animations === false) {
285
- postPromises.push(injectCSS(page, disableAnimations))
304
+ postPromises.push(
305
+ run({
306
+ fn: injectStyle(page, disableAnimations),
307
+ timeout: actionTimeout,
308
+ debug: 'disableAnimations'
309
+ })
310
+ )
286
311
  }
287
312
 
288
- const hideOrRemove = [
289
- hide && injectCSS(page, `${castArray(hide).join(', ')} { visibility: hidden !important; }`),
290
- remove && injectCSS(page, `${castArray(remove).join(', ')} { display: none !important; }`)
291
- ].filter(Boolean)
313
+ if (hide) {
314
+ postPromises.push(
315
+ run({
316
+ fn: injectStyle(page, `${castArray(hide).join(', ')} { visibility: hidden !important; }`),
317
+ timeout: actionTimeout,
318
+ debug: 'hide'
319
+ })
320
+ )
321
+ }
292
322
 
293
- if (hideOrRemove.length > 0) {
323
+ if (remove) {
294
324
  postPromises.push(
295
325
  run({
296
- fn: Promise.all(hideOrRemove),
297
- debug: { hideOrRemove: hideOrRemove.length }
326
+ fn: injectStyle(page, `${castArray(remove).join(', ')} { display: none !important; }`),
327
+ timeout: actionTimeout,
328
+ debug: 'remove'
298
329
  })
299
330
  )
300
331
  }
301
332
 
302
- const injections = [
303
- modules && injectScripts(page, modules, { type: 'modules' }),
304
- scripts && injectScripts(page, scripts),
305
- styles && injectStyles(page, styles)
306
- ].filter(Boolean)
333
+ if (modules) {
334
+ postPromises.push(
335
+ run({
336
+ fn: Promise.all(
337
+ castArray(modules).map(value => injectScript(page, value, { type: 'modules' }))
338
+ ),
339
+ timeout: actionTimeout,
340
+ debug: 'modules'
341
+ })
342
+ )
343
+ }
344
+
345
+ if (scripts) {
346
+ postPromises.push(
347
+ run({
348
+ fn: Promise.all(castArray(scripts).map(value => injectScript(page, value))),
349
+ timeout: actionTimeout,
350
+ debug: 'scripts'
351
+ })
352
+ )
353
+ }
307
354
 
308
- if (injections.length > 0) {
355
+ if (styles) {
309
356
  postPromises.push(
310
357
  run({
311
- fn: Promise.all(injections),
312
- debug: { injections: injections.length }
358
+ fn: Promise.all(castArray(styles).map(style => injectStyle(page, style))),
359
+ timeout: actionTimeout,
360
+ debug: 'styles'
313
361
  })
314
362
  )
315
363
  }
@@ -318,18 +366,21 @@ module.exports = ({
318
366
 
319
367
  if (click) {
320
368
  for (const selector of castArray(click)) {
321
- await run({ fn: page.click(selector), debug: { click: selector } })
369
+ await run({ fn: page.click(selector), timeout: actionTimeout, debug: { click: selector } })
322
370
  }
323
371
  }
324
372
 
325
373
  if (scroll) {
326
374
  await run({
327
375
  fn: page.$eval(scroll, el => el.scrollIntoView()),
376
+ timeout: actionTimeout,
328
377
  debug: { scroll }
329
378
  })
330
379
  }
331
380
 
332
- if (isWaitUntilAuto) await waitUntilAuto(page, { response: value, timeout })
381
+ if (isWaitUntilAuto) {
382
+ await waitUntilAuto(page, { response: value, timeout: actionTimeout * 2 })
383
+ }
333
384
 
334
385
  return { response: value, device }
335
386
  }
@@ -341,11 +392,13 @@ module.exports = ({
341
392
  goto.defaultViewport = defaultViewport
342
393
  goto.waitUntilAuto = _waitUntilAuto
343
394
  goto.timeout = baseTimeout
395
+ goto.actionTimeout = actionTimeout
396
+ goto.run = run
344
397
 
345
398
  return goto
346
399
  }
347
400
 
348
401
  module.exports.parseCookies = parseCookies
349
- module.exports.injectScripts = injectScripts
350
- module.exports.injectStyles = injectStyles
402
+ module.exports.injectScript = injectScript
403
+ module.exports.injectStyle = injectStyle
351
404
  module.exports.evasions = ALL_EVASIONS_KEYS