@browserless/pdf 13.6.4 → 13.6.6

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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/index.js +31 -16
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@browserless/pdf",
3
3
  "description": "Convert websites to high-quality PDFs with customizable margins, background printing, and optimized scaling.",
4
4
  "homepage": "https://browserless.js.org/#/?id=pdfurl-options",
5
- "version": "13.6.4",
5
+ "version": "13.6.6",
6
6
  "main": "src",
7
7
  "author": {
8
8
  "email": "hello@microlink.io",
@@ -30,8 +30,8 @@
30
30
  "website-to-pdf"
31
31
  ],
32
32
  "dependencies": {
33
- "@browserless/goto": "13.6.4",
34
- "@browserless/screenshot": "13.6.4",
33
+ "@browserless/goto": "13.6.6",
34
+ "@browserless/screenshot": "13.6.6",
35
35
  "@kikobeats/time-span": "~1.0.12",
36
36
  "debug-logfmt": "~1.4.10",
37
37
  "p-reflect": "~2.1.0",
@@ -47,5 +47,5 @@
47
47
  "test": "exit 0"
48
48
  },
49
49
  "license": "MIT",
50
- "gitHead": "c9d9abe1af82ce0ddf4ce1b6e8fe500c1b58532a"
50
+ "gitHead": "6c4a44b903f7e7382d49a27289bec6b3a1833108"
51
51
  }
package/src/index.js CHANGED
@@ -22,10 +22,13 @@ const PDF_DEFAULT_OPTS = {
22
22
  waitUntil: 'auto'
23
23
  }
24
24
 
25
- // Share of the action budget the readiness gate may consume in `auto` mode. The
26
- // remainder is reserved for the blank-SPA screenshot poll to re-wait, so the
27
- // gate can't starve the fallback while total prepare stays within one `timeout`.
28
- const READY_BUDGET_RATIO = 0.5
25
+ // Share of the phase's load allowance the readiness gate may consume in `auto`
26
+ // mode. Pages observed settling in 0.6-3.3s (a hydrating document is the slow
27
+ // end), so a quarter of the allowance ~3.9s at the default request budget —
28
+ // covers them with margin while keeping the cap well short of the render's
29
+ // share. The gate returns as soon as the page is quiet, so this bounds only a
30
+ // page that never settles.
31
+ const READY_BUDGET_RATIO = 0.25
29
32
 
30
33
  // Minimum visible characters for the text fast path. Matches the counting cap
31
34
  // in `waitForReady`'s snapshot, which stops walking text nodes once reached —
@@ -97,22 +100,34 @@ module.exports = ({ goto, ...gotoOpts } = {}) => {
97
100
  return
98
101
  }
99
102
 
103
+ // Surfaced to the caller: a page whose readiness could not be confirmed
104
+ // (`timedOut`) is a poor one to keep rendering on, so a caller reusing this
105
+ // load across page-ranges can choose a fresh context instead.
106
+ let readiness
107
+
100
108
  await goto(page, { ...rest, url, waitUntil, waitUntilAuto })
101
- async function waitUntilAuto (page) {
109
+ return readiness
110
+
111
+ async function waitUntilAuto (page, { timeout: autoTimeout } = {}) {
102
112
  await waitForDomStabilityResult(page)
103
113
  const timeout = goto.timeouts.action(rest.timeout)
104
- // One action budget shared by the readiness gate and the screenshot poll,
105
- // so worst-case prepare stays within a single `timeout` instead of one
106
- // per stage.
107
- const elapsed = timeSpan()
108
114
 
109
- // Cheap, navigation-tolerant readiness — no screenshots. Resolves once the
110
- // page is visually quiet (height stable, images decoded, load complete),
111
- // absorbing the client-side re-navigation that makes a screenshot poll
112
- // throw `Execution context was destroyed`. Capped at a share of the budget
113
- // so a slow gate still leaves the blank-SPA poll room to re-wait.
114
- const ready = await waitForReady(page, { timeout: Math.round(timeout * READY_BUDGET_RATIO) })
115
- debug('ready', { ...ready, duration: elapsed() })
115
+ // The readiness gate waits for a page to settle page-load work, not a
116
+ // small action. Budgeting it from `timeouts.action` (timeout/11) gave it
117
+ // ~1.2s while a hydrating document needs 2-3s, so it timed out on every
118
+ // tall page and the zero-capture fast path never fired. Budget it from
119
+ // the load allowance goto actually assigned to this phase; the gate
120
+ // returns as soon as the page is quiet, so this is a cap, not a cost.
121
+ const readyTime = timeSpan()
122
+ const ready = await waitForReady(page, {
123
+ timeout: Math.round((autoTimeout ?? timeout) * READY_BUDGET_RATIO)
124
+ })
125
+ readiness = ready
126
+ debug('ready', { ...ready, duration: readyTime() })
127
+
128
+ // The blank-page poll keeps its own action budget, measured from here so
129
+ // a slow gate cannot starve it.
130
+ const elapsed = timeSpan()
116
131
 
117
132
  // Fast path: the page settled with real painted content in a document
118
133
  // taller than the viewport — a visibly rendered image (not a tracking