@d-zero/puppeteer-scroll 4.0.3 → 4.0.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.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Max attempts for each `page.evaluate` call when it fails with a transient
3
+ * frame error. Chrome may briefly swap or re-attach the main frame during a
4
+ * long scroll or immediately after navigation, even when the target site is
5
+ * not doing anything observable. Three attempts with a 200 ms gap absorbs
6
+ * the typical re-attach window without masking a genuinely broken page.
7
+ */
8
+ export declare const MAX_EVALUATE_RETRIES = 3;
9
+ export declare const DETACHED_RETRY_DELAY_MS = 200;
10
+ /**
11
+ * Transient errors that occur when `page.evaluate` lands inside Puppeteer's
12
+ * own frame-swap or session-teardown window. Retrying after a short delay
13
+ * usually succeeds because the new execution context is then in place.
14
+ * @param error - Error caught from `page.evaluate`.
15
+ * @returns `true` when the error is a known transient frame/session error.
16
+ * @example
17
+ * ```ts
18
+ * try {
19
+ * await page.evaluate(...);
20
+ * } catch (error) {
21
+ * if (isTransientFrameError(error)) {
22
+ * // retry after a short delay
23
+ * } else {
24
+ * throw error;
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ export declare function isTransientFrameError(error: unknown): boolean;
30
+ /**
31
+ * Retries `evaluator` (typically a `page.evaluate` call) when it fails with
32
+ * a transient frame error. Non-transient errors are re-thrown immediately.
33
+ *
34
+ * Used both inside long-running scroll loops and around the single
35
+ * `page.evaluate` calls that bracket them, so that Chrome's brief
36
+ * post-navigation main-frame swap does not surface as an unrecoverable
37
+ * "Attempted to use detached Frame" error in the caller.
38
+ * @template T - Evaluator return type.
39
+ * @param evaluator - Thunk that performs a single `page.evaluate` call.
40
+ * @returns Whatever `evaluator` returns on success.
41
+ * @example
42
+ * ```ts
43
+ * const scrollHeight = await evaluateWithFrameRetry(() =>
44
+ * page.evaluate(() => document.body.scrollHeight),
45
+ * );
46
+ * ```
47
+ */
48
+ export declare function evaluateWithFrameRetry<T>(evaluator: () => Promise<T>): Promise<T>;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Max attempts for each `page.evaluate` call when it fails with a transient
3
+ * frame error. Chrome may briefly swap or re-attach the main frame during a
4
+ * long scroll or immediately after navigation, even when the target site is
5
+ * not doing anything observable. Three attempts with a 200 ms gap absorbs
6
+ * the typical re-attach window without masking a genuinely broken page.
7
+ */
8
+ export const MAX_EVALUATE_RETRIES = 3;
9
+ export const DETACHED_RETRY_DELAY_MS = 200;
10
+ /**
11
+ * Transient errors that occur when `page.evaluate` lands inside Puppeteer's
12
+ * own frame-swap or session-teardown window. Retrying after a short delay
13
+ * usually succeeds because the new execution context is then in place.
14
+ * @param error - Error caught from `page.evaluate`.
15
+ * @returns `true` when the error is a known transient frame/session error.
16
+ * @example
17
+ * ```ts
18
+ * try {
19
+ * await page.evaluate(...);
20
+ * } catch (error) {
21
+ * if (isTransientFrameError(error)) {
22
+ * // retry after a short delay
23
+ * } else {
24
+ * throw error;
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ export function isTransientFrameError(error) {
30
+ if (!(error instanceof Error))
31
+ return false;
32
+ return /Attempted to use detached Frame|Session closed|Execution context was destroyed/i.test(error.message);
33
+ }
34
+ /**
35
+ * Retries `evaluator` (typically a `page.evaluate` call) when it fails with
36
+ * a transient frame error. Non-transient errors are re-thrown immediately.
37
+ *
38
+ * Used both inside long-running scroll loops and around the single
39
+ * `page.evaluate` calls that bracket them, so that Chrome's brief
40
+ * post-navigation main-frame swap does not surface as an unrecoverable
41
+ * "Attempted to use detached Frame" error in the caller.
42
+ * @template T - Evaluator return type.
43
+ * @param evaluator - Thunk that performs a single `page.evaluate` call.
44
+ * @returns Whatever `evaluator` returns on success.
45
+ * @example
46
+ * ```ts
47
+ * const scrollHeight = await evaluateWithFrameRetry(() =>
48
+ * page.evaluate(() => document.body.scrollHeight),
49
+ * );
50
+ * ```
51
+ */
52
+ export async function evaluateWithFrameRetry(evaluator) {
53
+ let lastError;
54
+ for (let attempt = 0; attempt < MAX_EVALUATE_RETRIES; attempt++) {
55
+ try {
56
+ return await evaluator();
57
+ }
58
+ catch (error) {
59
+ lastError = error;
60
+ if (!isTransientFrameError(error))
61
+ throw error;
62
+ await new Promise((resolve) => setTimeout(resolve, DETACHED_RETRY_DELAY_MS));
63
+ }
64
+ }
65
+ throw lastError;
66
+ }
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { scrollAllOver } from './scroll-all-over.js';
2
+ export { evaluateWithFrameRetry, isTransientFrameError, } from './evaluate-with-frame-retry.js';
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { scrollAllOver } from './scroll-all-over.js';
2
+ export { evaluateWithFrameRetry, isTransientFrameError, } from './evaluate-with-frame-retry.js';
@@ -1,4 +1,5 @@
1
1
  import { delay } from '@d-zero/shared/delay';
2
+ import { evaluateWithFrameRetry } from './evaluate-with-frame-retry.js';
2
3
  import { resolveValue } from './resolve-value.js';
3
4
  /**
4
5
  * Number of consecutive iterations without scroll progress before bailing out.
@@ -9,49 +10,6 @@ import { resolveValue } from './resolve-value.js';
9
10
  * enough to confirm that scrolling is genuinely blocked.
10
11
  */
11
12
  const MAX_STUCK_ITERATIONS = 3;
12
- /**
13
- * Max attempts for each `page.evaluate` call when it fails with a transient
14
- * frame error (Chrome may briefly swap or re-attach the main frame during a
15
- * long scroll, even when the target site is not doing anything observable).
16
- * Three attempts with a 200 ms gap absorbs the typical re-attach window
17
- * without masking a genuinely broken page.
18
- */
19
- const MAX_EVALUATE_RETRIES = 3;
20
- const DETACHED_RETRY_DELAY_MS = 200;
21
- /**
22
- * Transient errors that occur when `page.evaluate` lands inside Puppeteer's
23
- * own frame-swap or session-teardown window. Retrying after a short delay
24
- * usually succeeds because the new execution context is then in place.
25
- * @param error - Error caught from `page.evaluate`.
26
- * @returns `true` when the error is a known transient frame/session error.
27
- */
28
- function isTransientFrameError(error) {
29
- if (!(error instanceof Error))
30
- return false;
31
- return /Attempted to use detached Frame|Session closed|Execution context was destroyed/i.test(error.message);
32
- }
33
- /**
34
- * Retries `evaluator` (typically a `page.evaluate` call) when it fails with
35
- * a transient frame error. Non-transient errors are re-thrown immediately.
36
- * @template T - Evaluator return type.
37
- * @param evaluator - Thunk that performs a single `page.evaluate` call.
38
- * @returns Whatever `evaluator` returns on success.
39
- */
40
- async function evaluateWithFrameRetry(evaluator) {
41
- let lastError;
42
- for (let attempt = 0; attempt < MAX_EVALUATE_RETRIES; attempt++) {
43
- try {
44
- return await evaluator();
45
- }
46
- catch (error) {
47
- lastError = error;
48
- if (!isTransientFrameError(error))
49
- throw error;
50
- await new Promise((resolve) => setTimeout(resolve, DETACHED_RETRY_DELAY_MS));
51
- }
52
- }
53
- throw lastError;
54
- }
55
13
  /**
56
14
  * Default interval range (ms) used when `options.interval` is omitted.
57
15
  * Randomized to mimic human-like reading pauses while staying close to the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d-zero/puppeteer-scroll",
3
- "version": "4.0.3",
3
+ "version": "4.0.4",
4
4
  "description": "Scroll function for puppeteer",
5
5
  "author": "D-ZERO",
6
6
  "license": "MIT",
@@ -36,5 +36,5 @@
36
36
  "url": "https://github.com/d-zero-dev/tools.git",
37
37
  "directory": "packages/@d-zero/puppeteer-scroll"
38
38
  },
39
- "gitHead": "d876ace142711051c337f7922931776526047cb0"
39
+ "gitHead": "9a26e6d8c1e996684691055ffc070547344b21e9"
40
40
  }