@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
package/dist/index.js
CHANGED
package/dist/scroll-all-over.js
CHANGED
|
@@ -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
|
+
"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": "
|
|
39
|
+
"gitHead": "9a26e6d8c1e996684691055ffc070547344b21e9"
|
|
40
40
|
}
|