obsidian-integration-testing 12.1.2 → 12.3.0
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/README.md +1 -5
- package/dist/lib/cjs/app-config.cjs +137 -0
- package/dist/lib/cjs/app-config.d.cts +190 -0
- package/dist/lib/cjs/appium-session-config.cjs +7 -1
- package/dist/lib/cjs/appium-session-config.d.cts +20 -0
- package/dist/lib/cjs/cdp-command-timeout-error.cjs +50 -0
- package/dist/lib/cjs/cdp-command-timeout-error.d.cts +48 -0
- package/dist/lib/cjs/connect-to-cdp.cjs +1 -1
- package/dist/lib/cjs/connect-to-cdp.d.cts +5 -0
- package/dist/lib/cjs/emulator-arguments.cjs +19 -3
- package/dist/lib/cjs/emulator-arguments.d.cts +44 -0
- package/dist/lib/cjs/emulator-device-id.cjs +1 -1
- package/dist/lib/cjs/emulator-device-id.d.cts +7 -6
- package/dist/lib/cjs/emulator-marker.cjs +169 -0
- package/dist/lib/cjs/emulator-marker.d.cts +224 -0
- package/dist/lib/cjs/emulator-reaper.cjs +248 -0
- package/dist/lib/cjs/emulator-reaper.d.cts +225 -0
- package/dist/lib/cjs/emulator-reclaim.cjs +312 -0
- package/dist/lib/cjs/emulator-reclaim.d.cts +179 -0
- package/dist/lib/cjs/eval-cap-exceeded-error.cjs +61 -0
- package/dist/lib/cjs/eval-cap-exceeded-error.d.cts +92 -0
- package/dist/lib/cjs/eval-cap.cjs +29 -0
- package/dist/lib/cjs/eval-cap.d.cts +43 -0
- package/dist/lib/cjs/global-setup-core.cjs +2 -3
- package/dist/lib/cjs/index.cjs +21 -1
- package/dist/lib/cjs/index.d.cts +7 -0
- package/dist/lib/cjs/library.cjs +1 -1
- package/dist/lib/cjs/poll-in-obsidian.cjs +1 -1
- package/dist/lib/cjs/poll-in-obsidian.d.cts +7 -2
- package/dist/lib/cjs/setup-lock.cjs +56 -8
- package/dist/lib/cjs/setup-lock.d.cts +53 -0
- package/dist/lib/cjs/soft-keyboard-geometry.cjs +17 -8
- package/dist/lib/cjs/soft-keyboard-geometry.d.cts +46 -9
- package/dist/lib/cjs/soft-keyboard.cjs +7 -4
- package/dist/lib/cjs/soft-keyboard.d.cts +16 -2
- package/dist/lib/cjs/transport-appium.cjs +70 -5
- package/dist/lib/cjs/transport-appium.d.cts +35 -0
- package/dist/lib/cjs/transport-desktop-cdp.cjs +98 -19
- package/dist/lib/cjs/transport-desktop-cdp.d.cts +44 -1
- package/dist/lib/cjs/transport-factory.cjs +297 -190
- package/dist/lib/cjs/transport-factory.d.cts +15 -0
- package/dist/lib/cjs/transport-options.cjs +1 -1
- package/dist/lib/cjs/transport-options.d.cts +38 -1
- package/dist/lib/cjs/webview-cdp.cjs +45 -14
- package/dist/lib/cjs/webview-cdp.d.cts +17 -0
- package/dist/lib/esm/app-config.d.mts +190 -0
- package/dist/lib/esm/app-config.mjs +110 -0
- package/dist/lib/esm/appium-session-config.d.mts +20 -0
- package/dist/lib/esm/appium-session-config.mjs +6 -1
- package/dist/lib/esm/cdp-command-timeout-error.d.mts +48 -0
- package/dist/lib/esm/cdp-command-timeout-error.mjs +26 -0
- package/dist/lib/esm/connect-to-cdp.d.mts +5 -0
- package/dist/lib/esm/connect-to-cdp.mjs +1 -1
- package/dist/lib/esm/emulator-arguments.d.mts +44 -0
- package/dist/lib/esm/emulator-arguments.mjs +16 -2
- package/dist/lib/esm/emulator-device-id.d.mts +7 -6
- package/dist/lib/esm/emulator-device-id.mjs +1 -1
- package/dist/lib/esm/emulator-marker.d.mts +224 -0
- package/dist/lib/esm/emulator-marker.mjs +134 -0
- package/dist/lib/esm/emulator-reaper.d.mts +225 -0
- package/dist/lib/esm/emulator-reaper.mjs +211 -0
- package/dist/lib/esm/emulator-reclaim.d.mts +179 -0
- package/dist/lib/esm/emulator-reclaim.mjs +291 -0
- package/dist/lib/esm/eval-cap-exceeded-error.d.mts +92 -0
- package/dist/lib/esm/eval-cap-exceeded-error.mjs +36 -0
- package/dist/lib/esm/eval-cap.d.mts +43 -0
- package/dist/lib/esm/eval-cap.mjs +5 -0
- package/dist/lib/esm/global-setup-core.mjs +6 -4
- package/dist/lib/esm/index.d.mts +7 -0
- package/dist/lib/esm/index.mjs +21 -1
- package/dist/lib/esm/library.mjs +1 -1
- package/dist/lib/esm/poll-in-obsidian.d.mts +7 -2
- package/dist/lib/esm/poll-in-obsidian.mjs +1 -1
- package/dist/lib/esm/setup-lock.d.mts +53 -0
- package/dist/lib/esm/setup-lock.mjs +52 -7
- package/dist/lib/esm/soft-keyboard-geometry.d.mts +46 -9
- package/dist/lib/esm/soft-keyboard-geometry.mjs +17 -8
- package/dist/lib/esm/soft-keyboard.d.mts +16 -2
- package/dist/lib/esm/soft-keyboard.mjs +7 -4
- package/dist/lib/esm/transport-appium.d.mts +35 -0
- package/dist/lib/esm/transport-appium.mjs +73 -5
- package/dist/lib/esm/transport-desktop-cdp.d.mts +44 -1
- package/dist/lib/esm/transport-desktop-cdp.mjs +98 -19
- package/dist/lib/esm/transport-factory.d.mts +15 -0
- package/dist/lib/esm/transport-factory.mjs +305 -184
- package/dist/lib/esm/transport-options.d.mts +38 -1
- package/dist/lib/esm/transport-options.mjs +1 -1
- package/dist/lib/esm/webview-cdp.d.mts +17 -0
- package/dist/lib/esm/webview-cdp.mjs +45 -14
- package/package.json +4 -4
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Stops the emulators this harness started, and **verifies** each stop — the
|
|
5
|
+
* marker-driven half of emulator ownership (`emulator-marker.ts`, **L56**).
|
|
6
|
+
*
|
|
7
|
+
* It lives apart from `transport-factory.ts` so that a process with no business
|
|
8
|
+
* loading the whole transport stack can still stop an emulator correctly. That
|
|
9
|
+
* process is the emulator reaper (`emulator-reaper.ts`): it runs detached from
|
|
10
|
+
* any test runner, and in this repo's own suites it runs straight from source
|
|
11
|
+
* under Node's type stripping, where a module reading the build-time
|
|
12
|
+
* `OBSIDIAN_METADATA` global — which the factory's import graph reaches —
|
|
13
|
+
* cannot load at all. So nothing this module imports may reach it either.
|
|
14
|
+
*/
|
|
15
|
+
import type { ChildProcess } from 'node:child_process';
|
|
16
|
+
import type { ProcessListEntry } from './emulator-backend.cjs';
|
|
17
|
+
/**
|
|
18
|
+
* Budget for one quick `adb` call — `adb devices`, a console command.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ADB_DEVICE_CHECK_TIMEOUT_IN_MILLISECONDS = 5000;
|
|
21
|
+
export declare const ADB_DUMPSYS_MAX_BUFFER_IN_BYTES = 8388608;
|
|
22
|
+
export declare const HOST_PROCESS_QUERY_TIMEOUT_IN_MILLISECONDS = 30000;
|
|
23
|
+
/**
|
|
24
|
+
* A host command and its arguments.
|
|
25
|
+
*/
|
|
26
|
+
export interface HostCommandQuery {
|
|
27
|
+
/**
|
|
28
|
+
The executable to run.
|
|
29
|
+
*/
|
|
30
|
+
readonly command: string;
|
|
31
|
+
/**
|
|
32
|
+
The command's arguments.
|
|
33
|
+
*/
|
|
34
|
+
readonly commandArguments: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parameters for {@link EmulatorReclaimer.reclaimLeftoverEmulators}.
|
|
38
|
+
*/
|
|
39
|
+
export interface ReclaimLeftoverEmulatorsParams {
|
|
40
|
+
/**
|
|
41
|
+
An AVD whose leftover is left alone — the one a preflight is about to adopt instead.
|
|
42
|
+
*/
|
|
43
|
+
readonly exceptAvdName?: string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* `'preflight'` spares an emulator another live harness process still owns.
|
|
46
|
+
* `'end-of-run'` does not: the caller holds the `android` lock with no run in
|
|
47
|
+
* flight — the run's own global teardown, or the emulator reaper after the
|
|
48
|
+
* run is gone — so that owner can only be one of the finished run's
|
|
49
|
+
* processes, which no longer has a turn to stop it.
|
|
50
|
+
*/
|
|
51
|
+
readonly scope: 'end-of-run' | 'preflight';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parameters for {@link EmulatorReclaimer.stopEmulator}.
|
|
55
|
+
*/
|
|
56
|
+
export interface StopEmulatorParams {
|
|
57
|
+
/**
|
|
58
|
+
The AVD name, named in the warning so the leftover is identifiable, and the key of its marker.
|
|
59
|
+
*/
|
|
60
|
+
readonly avdName: string;
|
|
61
|
+
/**
|
|
62
|
+
* The device the emulator is serving, shut down over its console and polled
|
|
63
|
+
* to decide whether it actually stopped. `undefined` when the emulator failed
|
|
64
|
+
* before any device appeared.
|
|
65
|
+
*/
|
|
66
|
+
readonly deviceId?: string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* The emulator launcher process this run spawned. `undefined` for a leftover
|
|
69
|
+
* this run took over, whose launcher belonged to another process.
|
|
70
|
+
*/
|
|
71
|
+
readonly emulatorProcess?: ChildProcess | undefined;
|
|
72
|
+
/**
|
|
73
|
+
The emulator PIDs this run owns, escalated to when the console and the launcher's tree kill leave one behind.
|
|
74
|
+
*/
|
|
75
|
+
readonly ownedEmulatorPids: readonly number[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Finds, stops and verifies the harness's emulators, reporting through the
|
|
79
|
+
* caller's log so each caller keeps its own prefix.
|
|
80
|
+
*/
|
|
81
|
+
export declare class EmulatorReclaimer {
|
|
82
|
+
private readonly log;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a reclaimer that reports under the caller's own log prefix.
|
|
85
|
+
*
|
|
86
|
+
* @param log - Receives every progress and verdict line.
|
|
87
|
+
*/
|
|
88
|
+
constructor(log: (message: string) => void);
|
|
89
|
+
/**
|
|
90
|
+
* Runs `adb devices` and returns its raw stdout.
|
|
91
|
+
*
|
|
92
|
+
* The raw listing is what teardown needs: `getConnectedDeviceIds` keeps only
|
|
93
|
+
* the `device` state, and an emulator on its way out answers `offline` while
|
|
94
|
+
* still holding the AVD — see `adb-device-list.ts`.
|
|
95
|
+
*
|
|
96
|
+
* @returns The raw `adb devices` output.
|
|
97
|
+
* @throws If adb could not be run at all.
|
|
98
|
+
*/
|
|
99
|
+
getDevicesOutput(): Promise<string>;
|
|
100
|
+
/**
|
|
101
|
+
* Lists every process on the host.
|
|
102
|
+
*
|
|
103
|
+
* A host always has processes, so a listing that parses to **zero** rows is a
|
|
104
|
+
* failed query however it exited, and comes back as `undefined` exactly like
|
|
105
|
+
* one that did not run — never as an empty list a caller could read as "no
|
|
106
|
+
* emulator is running".
|
|
107
|
+
*
|
|
108
|
+
* @returns The host's processes, or `undefined` when the listing failed.
|
|
109
|
+
*/
|
|
110
|
+
queryHostProcesses(): Promise<ProcessListEntry[] | undefined>;
|
|
111
|
+
/**
|
|
112
|
+
* Stops the emulators this harness started that no live run is responsible
|
|
113
|
+
* for, and drops the markers that no longer describe a running emulator.
|
|
114
|
+
*
|
|
115
|
+
* Only ever acts on a **marker-verified** emulator: one whose marker names a
|
|
116
|
+
* PID that is still a live emulator process. An emulator without a marker —
|
|
117
|
+
* booted by hand, by CI, or by another tool — is never touched, which keeps
|
|
118
|
+
* the L46 line: never a `qemu*` sweep.
|
|
119
|
+
*
|
|
120
|
+
* Callers must hold the `android` setup lock (L7), which is what makes a
|
|
121
|
+
* leftover safe to stop: no other Android run can be mid-flight on it.
|
|
122
|
+
*
|
|
123
|
+
* @param params - Which AVD to leave alone, and whether this run is ending.
|
|
124
|
+
*/
|
|
125
|
+
reclaimLeftoverEmulators(params: ReclaimLeftoverEmulatorsParams): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Stops an emulator this harness owns, and **verifies** it stopped.
|
|
128
|
+
*
|
|
129
|
+
* The console shutdown goes first because it is the only path that releases
|
|
130
|
+
* the AVD's `multiinstance.lock`; a `taskkill` leaves the lock behind, and a
|
|
131
|
+
* stale lock is what makes the next run fail with `Running multiple emulators
|
|
132
|
+
* with the same AVD` — a FATAL the emulator writes to its own stdout, where
|
|
133
|
+
* nobody sees it.
|
|
134
|
+
*
|
|
135
|
+
* Works without a launcher handle too: a leftover this run took over has only
|
|
136
|
+
* its PIDs, which is all the escalation below ever needed. The marker goes
|
|
137
|
+
* only with a **verified** stop, so an emulator that outlived this attempt
|
|
138
|
+
* stays convictable by the next one.
|
|
139
|
+
*
|
|
140
|
+
* @param params - The emulator process, the device it serves and the PIDs this run owns.
|
|
141
|
+
*/
|
|
142
|
+
stopEmulator(params: StopEmulatorParams): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* Decides whether the emulator this run started is really gone.
|
|
145
|
+
*
|
|
146
|
+
* Two independent proofs, cheapest first: none of the PIDs this run owns is
|
|
147
|
+
* alive, and the device no longer appears in `adb devices` **in any state** (a
|
|
148
|
+
* dying emulator answers `offline` while it still holds the AVD).
|
|
149
|
+
*
|
|
150
|
+
* @param params - The device and the PIDs this run owns.
|
|
151
|
+
* @returns `true` when nothing of this run's emulator is left.
|
|
152
|
+
*/
|
|
153
|
+
private checkIsEmulatorGone;
|
|
154
|
+
/**
|
|
155
|
+
* Asks the emulator to shut itself down over its console.
|
|
156
|
+
*
|
|
157
|
+
* Preferred over killing the process outright because it is the path that
|
|
158
|
+
* releases the AVD's `multiinstance.lock`. Best-effort: a console that does
|
|
159
|
+
* not answer is reported and the caller falls through to the kill.
|
|
160
|
+
*
|
|
161
|
+
* @param deviceId - The emulator's device ID.
|
|
162
|
+
*/
|
|
163
|
+
private killEmulatorConsole;
|
|
164
|
+
/**
|
|
165
|
+
* Acts on one emulator marker for {@link reclaimLeftoverEmulators}.
|
|
166
|
+
*
|
|
167
|
+
* @param marker - The marker to judge.
|
|
168
|
+
* @param liveEmulatorPids - The emulator processes currently running on the host.
|
|
169
|
+
* @param scope - Whether an emulator another live harness process owns is spared.
|
|
170
|
+
*/
|
|
171
|
+
private reclaimLeftoverEmulator;
|
|
172
|
+
/**
|
|
173
|
+
* Polls until this run's emulator is gone, or the budget elapses.
|
|
174
|
+
*
|
|
175
|
+
* @param params - The device, the PIDs this run owns, and the budget.
|
|
176
|
+
* @returns `true` when the emulator disappeared within the budget.
|
|
177
|
+
*/
|
|
178
|
+
private waitForEmulatorStopped;
|
|
179
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var eval_cap_exceeded_error_exports = {};
|
|
20
|
+
__export(eval_cap_exceeded_error_exports, {
|
|
21
|
+
EvalCapExceededError: () => EvalCapExceededError,
|
|
22
|
+
isScriptTimeoutError: () => isScriptTimeoutError
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(eval_cap_exceeded_error_exports);
|
|
25
|
+
const SCRIPT_TIMEOUT_PATTERN = /script\s*timeout/i;
|
|
26
|
+
class EvalCapExceededError extends Error {
|
|
27
|
+
/**
|
|
28
|
+
The per-eval cap the closure outran, in milliseconds.
|
|
29
|
+
*/
|
|
30
|
+
capInMilliseconds;
|
|
31
|
+
/**
|
|
32
|
+
How the transport that enforced the cap was named in the message.
|
|
33
|
+
*/
|
|
34
|
+
transportName;
|
|
35
|
+
/**
|
|
36
|
+
* Creates the error from the cap, the transport, and the raw error it replaces.
|
|
37
|
+
*
|
|
38
|
+
* @param params - The cap, the transport, the option that sets the cap, and the underlying error.
|
|
39
|
+
*/
|
|
40
|
+
constructor(params) {
|
|
41
|
+
super(buildMessage(params), { cause: params.cause });
|
|
42
|
+
this.name = "EvalCapExceededError";
|
|
43
|
+
this.capInMilliseconds = params.capInMilliseconds;
|
|
44
|
+
this.transportName = params.transportName;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isScriptTimeoutError(error) {
|
|
48
|
+
if (!(error instanceof Error)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return SCRIPT_TIMEOUT_PATTERN.test(error.message) || SCRIPT_TIMEOUT_PATTERN.test(error.name);
|
|
52
|
+
}
|
|
53
|
+
function buildMessage(params) {
|
|
54
|
+
return `A single evalInObsidian closure ran longer than the ${params.transportName} per-eval cap of ${String(params.capInMilliseconds)}ms, so it was killed mid-flight. This is a property of the closure, not of the device or the app: everything awaited inside one closure shares that one budget, including every \`lib.waitUntil\` timeout and every settle \`sleep\`. Do the waiting from Node instead \u2014 \`pollInObsidian\` runs a short \`poll\` closure repeatedly until a Node-side \`until\` accepts, so no single eval is ever long. Raise \`${params.optionName}\` only for a closure that genuinely cannot be split.`;
|
|
55
|
+
}
|
|
56
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
57
|
+
0 && (module.exports = {
|
|
58
|
+
EvalCapExceededError,
|
|
59
|
+
isScriptTimeoutError
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2V2YWwtY2FwLWV4Y2VlZGVkLWVycm9yLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogVGhlIG9uZSBlcnJvciBib3RoIHRyYW5zcG9ydHMgcmFpc2Ugd2hlbiBhIHNpbmdsZSBgZXZhbEluT2JzaWRpYW5gIGNsb3N1cmVcbiAqIG91dHJ1bnMgdGhlIHBlci1ldmFsIGNhcCwgYW5kIHRoZSBwcmVkaWNhdGUgdGhhdCByZWNvZ25pemVzIHRoZSByYXcgdHJhbnNwb3J0XG4gKiBlcnJvciBpdCByZXBsYWNlcy5cbiAqXG4gKiBUaGUgY2FwIGl0c2VsZiBpcyBub3QgdGhlIHByb2JsZW0gdGhpcyBtb2R1bGUgc29sdmVzIFx1MjAxNCB0aGUgZGlhZ25vc2lzIGlzLlxuICogRGVza3RvcCBzdXJmYWNlcyB0aGUgb3ZlcnJ1biBhcyBhIGdlbmVyaWNcbiAqIGBDRFAgY29tbWFuZCB0aW1lZCBvdXQgLi4uIDogUnVudGltZS5ldmFsdWF0ZWAsIHdoaWNoIG5ldmVyIG5hbWVzIHRoZSB0ZXN0J3NcbiAqIG93biB3YWl0IGFuZCBzbyByZWFkcyBhcyBhIGJyb2tlbiBkZXZpY2Ugb3IgYSB3ZWRnZWQgYXBwIFx1MjAxNCBhIHBsdWdpbiByZWxlYXNlIHdhc1xuICogb25jZSBoZWxkIGZvciB0d28gZGF5cyBieSB0aGF0IHJlYWRpbmcsIHdpdGggYSBoZWFsdGh5IGVtdWxhdG9yIGJsYW1lZCBmb3JcbiAqIGhhdmluZyBubyBuZXR3b3JrLlxuICpcbiAqIEFuZHJvaWQgaXMgd29yc2UsIGJlY2F1c2UgaXQgc3VyZmFjZXMgTk9USElORy4gT24gYSBsaXZlIGVtdWxhdG9yIHRoZSBjbG9zdXJlXG4gKiB3YXMgbWVhc3VyZWQgY29tcGxldGluZyBpbiB0aGUgZ3Vlc3Qgb24gc2NoZWR1bGUgXHUyMDE0IHRpbWVycyBhcm1lZCBhdCAzMHMgYW5kIDQwcyBmaXJlZCB3aXRoaW5cbiAqIH4xM21zIG9mIG5vbWluYWwgb24gYSB2aXNpYmxlLCBmb2N1c2VkIHBhZ2UgXHUyMDE0IHdoaWxlIGl0cyBFeGVjdXRlIFNjcmlwdCByZXNwb25zZVxuICogbmV2ZXIgcmVhY2hlZCB0aGUgY2xpZW50LCBzbyB0aGUgY2FsbCBodW5nIHVudGlsIHdoaWNoZXZlciBvdXRlciBidWRnZXQgZ2F2ZSB1cFxuICogZmlyc3QuIEEgaGFuZyBuYW1lcyBub3RoaW5nIGF0IGFsbCwgd2hpY2ggaXMgd2h5IHRoZSBBbmRyb2lkIGNhcCBpcyBlbmZvcmNlZCBieVxuICogdGhlIHRyYW5zcG9ydCBvbiB0aGUgTm9kZSBzaWRlIHJhdGhlciB0aGFuIGJ5IHRoZSBgdGltZW91dHMuc2NyaXB0YCBjYXBhYmlsaXR5XG4gKiBpdCBhbHNvIGRlY2xhcmVzIGFuZCB0aGF0IG5vdGhpbmcgYWN0cyBvbi5cbiAqXG4gKiBCb3RoIHRyYW5zcG9ydHMgdGhlcmVmb3JlIGZ1bm5lbCBpbnRvIHRoZSBtZXNzYWdlIGJlbG93LCB3aGljaCBzYXlzIHdoYXQgdGhlIGNhcFxuICogaXMsIHdoaWNoIHRyYW5zcG9ydCBlbmZvcmNlZCBpdCwgYW5kIHdoYXQgdG8gZG8gaW5zdGVhZC5cbiAqXG4gKiBBIGNsb3N1cmUgdGhhdCBuZWVkcyB0byB3YWl0IGxvbmdlciB0aGFuIHRoZSBjYXAgc2hvdWxkIG5vdCBiZSB3YWl0aW5nIGluc2lkZVxuICogT2JzaWRpYW4gYXQgYWxsLiBgcG9sbEluT2JzaWRpYW5gIGlzIHRoZSBzYW5jdGlvbmVkIHNoYXBlOiBzaG9ydCBjbG9zdXJlcywgYW5kXG4gKiB0aGUgd2FpdGluZyBkb25lIGZyb20gTm9kZS5cbiAqL1xuXG4vKlxuICogVGhlIFczQyBlcnJvciBjb2RlIGlzIHRoZSBzcGFjZWQgYHNjcmlwdCB0aW1lb3V0YCwgd2hpbGUgYSBjbGllbnQgdGhhdCB0dXJucyBpdCBpbnRvIGEgdHlwZSBzcGVsbHMgdGhlXG4gKiBTYW1lIHRoaW5nIGFzIGBTY3JpcHRUaW1lb3V0RXJyb3JgIFx1MjAxNCBoZW5jZSB0aGUgb3B0aW9uYWwgd2hpdGVzcGFjZSwgd2hpY2ggbGV0cyBvbmUgcGF0dGVybiByZWFkIGJvdGguXG4gKi9cbmNvbnN0IFNDUklQVF9USU1FT1VUX1BBVFRFUk4gPSAvc2NyaXB0XFxzKnRpbWVvdXQvaTtcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgRXZhbENhcEV4Y2VlZGVkRXJyb3J9J3MgY29uc3RydWN0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXZhbENhcEV4Y2VlZGVkRXJyb3JDb25zdHJ1Y3RvclBhcmFtcyB7XG4gIC8qKlxuICBUaGUgcGVyLWV2YWwgY2FwIHRoZSBjbG9zdXJlIG91dHJhbiwgaW4gbWlsbGlzZWNvbmRzLlxuICAgKi9cbiAgcmVhZG9ubHkgY2FwSW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICAvKipcbiAgVGhlIHVuZGVybHlpbmcgdHJhbnNwb3J0IGVycm9yLCBrZXB0IGFzIHRoZSBgY2F1c2VgIHNvIHRoZSByYXcgZGlhZ25vc2lzIGlzIG5vdCBsb3N0LlxuICAgKi9cbiAgcmVhZG9ubHkgY2F1c2U6IHVua25vd247XG5cbiAgLyoqXG4gIFRoZSBuYW1lIG9mIHRoZSBvcHRpb24gdGhhdCBzZXRzIHRoZSBjYXAgb24gdGhpcyB0cmFuc3BvcnQsIHNvIHRoZSBtZXNzYWdlIGNhbiBuYW1lIHRoZSByZWFsIGtub2IuXG4gICAqL1xuICByZWFkb25seSBvcHRpb25OYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gIEhvdyB0byByZWZlciB0byB0aGUgdHJhbnNwb3J0IHRoYXQgZW5mb3JjZWQgdGhlIGNhcCwgZS5nLiBgJ0FuZHJvaWQgKEFwcGl1bSknYC5cbiAgICovXG4gIHJlYWRvbmx5IHRyYW5zcG9ydE5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaHJvd24gd2hlbiBvbmUgYGV2YWxJbk9ic2lkaWFuYCBjbG9zdXJlIHJhbiBsb25nZXIgdGhhbiB0aGUgdHJhbnNwb3J0J3NcbiAqIHBlci1ldmFsIGNhcC5cbiAqXG4gKiBDYXJyaWVzIHRoZSBjYXAgYW5kIHRoZSB0cmFuc3BvcnQgc28gYSBjYWxsZXIgY2FuIGBpbnN0YW5jZW9mYC1tYXRjaCwgYW5kIHRoZVxuICogb3JpZ2luYWwgdHJhbnNwb3J0IGVycm9yIGFzIGBjYXVzZWAuXG4gKi9cbmV4cG9ydCBjbGFzcyBFdmFsQ2FwRXhjZWVkZWRFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gIFRoZSBwZXItZXZhbCBjYXAgdGhlIGNsb3N1cmUgb3V0cmFuLCBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY2FwSW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICAvKipcbiAgSG93IHRoZSB0cmFuc3BvcnQgdGhhdCBlbmZvcmNlZCB0aGUgY2FwIHdhcyBuYW1lZCBpbiB0aGUgbWVzc2FnZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB0cmFuc3BvcnROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGVycm9yIGZyb20gdGhlIGNhcCwgdGhlIHRyYW5zcG9ydCwgYW5kIHRoZSByYXcgZXJyb3IgaXQgcmVwbGFjZXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgY2FwLCB0aGUgdHJhbnNwb3J0LCB0aGUgb3B0aW9uIHRoYXQgc2V0cyB0aGUgY2FwLCBhbmQgdGhlIHVuZGVybHlpbmcgZXJyb3IuXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zOiBFdmFsQ2FwRXhjZWVkZWRFcnJvckNvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgc3VwZXIoYnVpbGRNZXNzYWdlKHBhcmFtcyksIHsgY2F1c2U6IHBhcmFtcy5jYXVzZSB9KTtcbiAgICB0aGlzLm5hbWUgPSAnRXZhbENhcEV4Y2VlZGVkRXJyb3InO1xuICAgIHRoaXMuY2FwSW5NaWxsaXNlY29uZHMgPSBwYXJhbXMuY2FwSW5NaWxsaXNlY29uZHM7XG4gICAgdGhpcy50cmFuc3BvcnROYW1lID0gcGFyYW1zLnRyYW5zcG9ydE5hbWU7XG4gIH1cbn1cblxuLyoqXG4gKiBXaGV0aGVyIGFuIGVycm9yIGlzIGEgV2ViRHJpdmVyIHNjcmlwdCB0aW1lb3V0IFx1MjAxNCB0aGUgVzNDIGVycm9yIGEgZHJpdmVyIHdvdWxkXG4gKiByYWlzZSBpZiBpdCBlbmZvcmNlZCBgdGltZW91dHMuc2NyaXB0YC5cbiAqXG4gKiBNYXRjaGVkIG9uIHRoZSBtZXNzYWdlIHJhdGhlciB0aGFuIG9uIGEgdHlwZSwgYmVjYXVzZSB0aGUgZXJyb3IgYXJyaXZlcyBhcyBhXG4gKiBnZW5lcmljIGBXZWJEcml2ZXJFcnJvcmAgd2hvc2Ugb25seSBkaXN0aW5ndWlzaGluZyBtYXJrIGlzIHRoZSBXM0MgZXJyb3IgY29kZVxuICogaW4gaXRzIHRleHQuXG4gKlxuICogKipUaGlzIGRyaXZlciBuZXZlciByYWlzZXMgaXQuKiogVWlBdXRvbWF0b3IyIHdhcyBtZWFzdXJlZCBhY2NlcHRpbmcgdGhlXG4gKiBjYXBhYmlsaXR5LCByZXBvcnRpbmcgaXQgYmFjaywgYW5kIGVuZm9yY2luZyBub3RoaW5nLiBUaGUgcHJlZGljYXRlIGlzIGtlcHRcbiAqIGJlY2F1c2UgaXQgY29zdHMgbm90aGluZywgaXQgaXMgdGhlIHJpZ2h0IHRyYW5zbGF0aW9uIGlmIGEgZnV0dXJlIGRyaXZlciBkb2VzXG4gKiBlbmZvcmNlIHRoZSBjYXBhYmlsaXR5LCBhbmQgaXQga2VlcHMgb25lIGVycm9yIGNvdmVyaW5nIG9uZSBjb25kaXRpb24gb24gYm90aFxuICogdHJhbnNwb3J0cyBcdTIwMTQgYnV0IHRoZSBBbmRyb2lkIGNhcCBpcyBlbmZvcmNlZCBOb2RlLXNpZGUsIGFuZCB0aGlzIGlzIG5vdCB3aGF0XG4gKiBlbmZvcmNlcyBpdC5cbiAqXG4gKiBAcGFyYW0gZXJyb3IgLSBUaGUgZXJyb3IgdGhyb3duIGJ5IHRoZSB0cmFuc3BvcnQuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgZXJyb3IgaXMgYSBzY3JpcHQgdGltZW91dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2NyaXB0VGltZW91dEVycm9yKGVycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIGlmICghKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIFNDUklQVF9USU1FT1VUX1BBVFRFUk4udGVzdChlcnJvci5tZXNzYWdlKSB8fCBTQ1JJUFRfVElNRU9VVF9QQVRURVJOLnRlc3QoZXJyb3IubmFtZSk7XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBzaGFyZWQgbWVzc2FnZSBib3RoIHRyYW5zcG9ydHMgcmVwb3J0LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgY2FwLCB0aGUgdHJhbnNwb3J0LCBhbmQgdGhlIG9wdGlvbiB0aGF0IHNldHMgdGhlIGNhcC5cbiAqIEByZXR1cm5zIFRoZSBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBidWlsZE1lc3NhZ2UocGFyYW1zOiBFdmFsQ2FwRXhjZWVkZWRFcnJvckNvbnN0cnVjdG9yUGFyYW1zKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBBIHNpbmdsZSBldmFsSW5PYnNpZGlhbiBjbG9zdXJlIHJhbiBsb25nZXIgdGhhbiB0aGUgJHtwYXJhbXMudHJhbnNwb3J0TmFtZX0gcGVyLWV2YWwgY2FwIG9mICR7U3RyaW5nKHBhcmFtcy5jYXBJbk1pbGxpc2Vjb25kcyl9bXMsIHNvIGl0IHdhcyBraWxsZWQgbWlkLWZsaWdodC4gVGhpcyBpcyBhIHByb3BlcnR5IG9mIHRoZSBjbG9zdXJlLCBub3Qgb2YgdGhlIGRldmljZSBvciB0aGUgYXBwOiBgXG4gICAgKyAnZXZlcnl0aGluZyBhd2FpdGVkIGluc2lkZSBvbmUgY2xvc3VyZSBzaGFyZXMgdGhhdCBvbmUgYnVkZ2V0LCBpbmNsdWRpbmcgZXZlcnkgYGxpYi53YWl0VW50aWxgIHRpbWVvdXQgJ1xuICAgICsgJ2FuZCBldmVyeSBzZXR0bGUgYHNsZWVwYC4gRG8gdGhlIHdhaXRpbmcgZnJvbSBOb2RlIGluc3RlYWQgXHUyMDE0IGBwb2xsSW5PYnNpZGlhbmAgcnVucyBhIHNob3J0IGBwb2xsYCAnXG4gICAgKyAnY2xvc3VyZSByZXBlYXRlZGx5IHVudGlsIGEgTm9kZS1zaWRlIGB1bnRpbGAgYWNjZXB0cywgc28gbm8gc2luZ2xlIGV2YWwgaXMgZXZlciBsb25nLiBSYWlzZSAnXG4gICAgKyBgXFxgJHtwYXJhbXMub3B0aW9uTmFtZX1cXGAgb25seSBmb3IgYSBjbG9zdXJlIHRoYXQgZ2VudWluZWx5IGNhbm5vdCBiZSBzcGxpdC5gO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBa0NBLE1BQU0seUJBQXlCO0FBa0N4QixNQUFNLDZCQUE2QixNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFJOUI7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT1QsWUFBWSxRQUErQztBQUNoRSxVQUFNLGFBQWEsTUFBTSxHQUFHLEVBQUUsT0FBTyxPQUFPLE1BQU0sQ0FBQztBQUNuRCxTQUFLLE9BQU87QUFDWixTQUFLLG9CQUFvQixPQUFPO0FBQ2hDLFNBQUssZ0JBQWdCLE9BQU87QUFBQSxFQUM5QjtBQUNGO0FBb0JPLFNBQVMscUJBQXFCLE9BQXlCO0FBQzVELE1BQUksRUFBRSxpQkFBaUIsUUFBUTtBQUM3QixXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sdUJBQXVCLEtBQUssTUFBTSxPQUFPLEtBQUssdUJBQXVCLEtBQUssTUFBTSxJQUFJO0FBQzdGO0FBUUEsU0FBUyxhQUFhLFFBQXVEO0FBQzNFLFNBQU8sdURBQXVELE9BQU8sYUFBYSxvQkFBb0IsT0FBTyxPQUFPLGlCQUFpQixDQUFDLDBaQUk3SCxPQUFPLFVBQVU7QUFDNUI7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* The one error both transports raise when a single `evalInObsidian` closure
|
|
5
|
+
* outruns the per-eval cap, and the predicate that recognizes the raw transport
|
|
6
|
+
* error it replaces.
|
|
7
|
+
*
|
|
8
|
+
* The cap itself is not the problem this module solves — the diagnosis is.
|
|
9
|
+
* Desktop surfaces the overrun as a generic
|
|
10
|
+
* `CDP command timed out ... : Runtime.evaluate`, which never names the test's
|
|
11
|
+
* own wait and so reads as a broken device or a wedged app — a plugin release was
|
|
12
|
+
* once held for two days by that reading, with a healthy emulator blamed for
|
|
13
|
+
* having no network.
|
|
14
|
+
*
|
|
15
|
+
* Android is worse, because it surfaces NOTHING. On a live emulator the closure
|
|
16
|
+
* was measured completing in the guest on schedule — timers armed at 30s and 40s fired within
|
|
17
|
+
* ~13ms of nominal on a visible, focused page — while its Execute Script response
|
|
18
|
+
* never reached the client, so the call hung until whichever outer budget gave up
|
|
19
|
+
* first. A hang names nothing at all, which is why the Android cap is enforced by
|
|
20
|
+
* the transport on the Node side rather than by the `timeouts.script` capability
|
|
21
|
+
* it also declares and that nothing acts on.
|
|
22
|
+
*
|
|
23
|
+
* Both transports therefore funnel into the message below, which says what the cap
|
|
24
|
+
* is, which transport enforced it, and what to do instead.
|
|
25
|
+
*
|
|
26
|
+
* A closure that needs to wait longer than the cap should not be waiting inside
|
|
27
|
+
* Obsidian at all. `pollInObsidian` is the sanctioned shape: short closures, and
|
|
28
|
+
* the waiting done from Node.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Parameters for {@link EvalCapExceededError}'s constructor.
|
|
32
|
+
*/
|
|
33
|
+
export interface EvalCapExceededErrorConstructorParams {
|
|
34
|
+
/**
|
|
35
|
+
The per-eval cap the closure outran, in milliseconds.
|
|
36
|
+
*/
|
|
37
|
+
readonly capInMilliseconds: number;
|
|
38
|
+
/**
|
|
39
|
+
The underlying transport error, kept as the `cause` so the raw diagnosis is not lost.
|
|
40
|
+
*/
|
|
41
|
+
readonly cause: unknown;
|
|
42
|
+
/**
|
|
43
|
+
The name of the option that sets the cap on this transport, so the message can name the real knob.
|
|
44
|
+
*/
|
|
45
|
+
readonly optionName: string;
|
|
46
|
+
/**
|
|
47
|
+
How to refer to the transport that enforced the cap, e.g. `'Android (Appium)'`.
|
|
48
|
+
*/
|
|
49
|
+
readonly transportName: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Thrown when one `evalInObsidian` closure ran longer than the transport's
|
|
53
|
+
* per-eval cap.
|
|
54
|
+
*
|
|
55
|
+
* Carries the cap and the transport so a caller can `instanceof`-match, and the
|
|
56
|
+
* original transport error as `cause`.
|
|
57
|
+
*/
|
|
58
|
+
export declare class EvalCapExceededError extends Error {
|
|
59
|
+
/**
|
|
60
|
+
The per-eval cap the closure outran, in milliseconds.
|
|
61
|
+
*/
|
|
62
|
+
readonly capInMilliseconds: number;
|
|
63
|
+
/**
|
|
64
|
+
How the transport that enforced the cap was named in the message.
|
|
65
|
+
*/
|
|
66
|
+
readonly transportName: string;
|
|
67
|
+
/**
|
|
68
|
+
* Creates the error from the cap, the transport, and the raw error it replaces.
|
|
69
|
+
*
|
|
70
|
+
* @param params - The cap, the transport, the option that sets the cap, and the underlying error.
|
|
71
|
+
*/
|
|
72
|
+
constructor(params: EvalCapExceededErrorConstructorParams);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Whether an error is a WebDriver script timeout — the W3C error a driver would
|
|
76
|
+
* raise if it enforced `timeouts.script`.
|
|
77
|
+
*
|
|
78
|
+
* Matched on the message rather than on a type, because the error arrives as a
|
|
79
|
+
* generic `WebDriverError` whose only distinguishing mark is the W3C error code
|
|
80
|
+
* in its text.
|
|
81
|
+
*
|
|
82
|
+
* **This driver never raises it.** UiAutomator2 was measured accepting the
|
|
83
|
+
* capability, reporting it back, and enforcing nothing. The predicate is kept
|
|
84
|
+
* because it costs nothing, it is the right translation if a future driver does
|
|
85
|
+
* enforce the capability, and it keeps one error covering one condition on both
|
|
86
|
+
* transports — but the Android cap is enforced Node-side, and this is not what
|
|
87
|
+
* enforces it.
|
|
88
|
+
*
|
|
89
|
+
* @param error - The error thrown by the transport.
|
|
90
|
+
* @returns `true` when the error is a script timeout.
|
|
91
|
+
*/
|
|
92
|
+
export declare function isScriptTimeoutError(error: unknown): boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var eval_cap_exports = {};
|
|
20
|
+
__export(eval_cap_exports, {
|
|
21
|
+
DEFAULT_EVAL_CAP_IN_MILLISECONDS: () => DEFAULT_EVAL_CAP_IN_MILLISECONDS
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(eval_cap_exports);
|
|
24
|
+
const DEFAULT_EVAL_CAP_IN_MILLISECONDS = 3e4;
|
|
25
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
26
|
+
0 && (module.exports = {
|
|
27
|
+
DEFAULT_EVAL_CAP_IN_MILLISECONDS
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2V2YWwtY2FwLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogVGhlIHBlci1ldmFsIGNhcDogaG93IGxvbmcgYSBzaW5nbGUgYGV2YWxJbk9ic2lkaWFuYCBjbG9zdXJlIG1heSBydW4gYmVmb3JlXG4gKiB0aGUgdHJhbnNwb3J0IGNhcnJ5aW5nIGl0IGdpdmVzIHVwLlxuICpcbiAqIEl0IGxpdmVzIGluIGl0cyBvd24gbW9kdWxlLCBhbmQgaXMgcmUtZXhwb3J0ZWQgZnJvbSB0aGUgcGFja2FnZSByb290LCBiZWNhdXNlXG4gKiBpdCBpcyB0aGUgc2luZ2xlIG1vc3QgbG9hZC1iZWFyaW5nIG51bWJlciBhIHRlc3QgYXV0aG9yIGhhcyB0byByZXNwZWN0IFx1MjAxNCBhbmRcbiAqIHVudGlsIHRoaXMgbW9kdWxlIGV4aXN0ZWQgdGhlcmUgd2FzIG5vdGhpbmcgdG8gaW1wb3J0LiBCb3RoIHRyYW5zcG9ydHMgaGVsZFxuICogdGhlIHNhbWUgMzBzIHByaXZhdGVseSwgc28gZXZlcnkgY29uc3VtZXIgdGhhdCBuZWVkZWQgdG8gc2l6ZSBhIGNsb3N1cmVcbiAqIHJlc3RhdGVkIGl0IGFzIGEgbGl0ZXJhbCB3aXRoIGEgY29tbWVudCBzYXlpbmcgd2hlcmUgdGhlIG51bWJlciBjYW1lIGZyb20uXG4gKiBUaGF0IGlzIGEgbWlycm9yIG5vdGhpbmcgbWFpbnRhaW5zOiByYWlzZSBhIGNhcCBoZXJlIGFuZCBldmVyeSByZXN0YXRlbWVudCBpc1xuICogc2lsZW50bHkgd3JvbmcgaW4gdGhlIGRpcmVjdGlvbiB0aGF0IHByb2R1Y2VzIHRoZSB1bnJlYWRhYmxlIGZhaWx1cmUsIGJlY2F1c2VcbiAqIHRoZSBjb25zdW1lciBnb2VzIG9uIGJlbGlldmluZyBpdCBoYXMgaGVhZHJvb20gaXQgbm8gbG9uZ2VyIGhhcy5cbiAqXG4gKiAqKlRoZSB0d28gdHJhbnNwb3J0cyBzaGFyZSB0aGlzIE9ORSBjb25zdGFudCByYXRoZXIgdGhhbiBhZ3JlZWluZyBieVxuICogY29pbmNpZGVuY2UuKiogVGhleSBlbmZvcmNlIGl0IHRocm91Z2ggZGlmZmVyZW50IGtub2JzIFx1MjAxNCBkZXNrdG9wIGJvdW5kcyB0aGVcbiAqIGBSdW50aW1lLmV2YWx1YXRlYCBDRFAgY29tbWFuZCAoYGNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHNgKSwgQW5kcm9pZFxuICogYm91bmRzIHRoZSBFeGVjdXRlIFNjcmlwdCBjYWxsIE5vZGUtc2lkZSAoYHNjcmlwdFRpbWVvdXRJbk1pbGxpc2Vjb25kc2ApIFx1MjAxNFxuICogYnV0IHRoZSBrbm9icyBhcmUgdHdvIGltcGxlbWVudGF0aW9ucyBvZiBvbmUgcG9saWN5LCBub3QgdHdvIHBvbGljaWVzIHRoYXRcbiAqIGhhcHBlbiB0byBhZ3JlZS4gQSByZWFkZXIgb2YgZWl0aGVyIGRlZmF1bHQgbm93IHNlZXMgd2hpY2ggaXQgaXMuXG4gKi9cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBwZXItZXZhbCBjYXAsIGluIG1pbGxpc2Vjb25kczogdGhlIGJ1ZGdldCBvbmUgYGV2YWxJbk9ic2lkaWFuYFxuICogY2xvc3VyZSBoYXMgdG8gZml0IGluc2lkZS5cbiAqXG4gKiBFdmVyeXRoaW5nIGF3YWl0ZWQgaW5zaWRlIGEgc2luZ2xlIGNsb3N1cmUgc2hhcmVzIHRoaXMgb25lIGJ1ZGdldCBcdTIwMTQgZXZlcnlcbiAqIGBsaWIud2FpdFVudGlsYCB0aW1lb3V0IGFuZCBldmVyeSBzZXR0bGUgYHNsZWVwYCBcdTIwMTQgc28gYSBjbG9zdXJlJ3MgZGVjbGFyZWRcbiAqIHdhaXRzIGhhdmUgdG8gc3VtIHRvIGxlc3MgdGhhbiB0aGlzLCBub3QgbWVyZWx5IGJlIGluZGl2aWR1YWxseSBzaG9ydGVyLlxuICpcbiAqIEFuIG92ZXJydW4gaXMgcmVwb3J0ZWQgYXMgYEV2YWxDYXBFeGNlZWRlZEVycm9yYCwgd2hpY2ggbmFtZXMgdGhlIGNhcCwgdGhlXG4gKiB0cmFuc3BvcnQgdGhhdCBlbmZvcmNlZCBpdCwgYW5kIHRoZSBvcHRpb24gdGhhdCBzZXRzIGl0LiBSYWlzaW5nIHRoYXQgb3B0aW9uXG4gKiBpcyBhbG1vc3QgbmV2ZXIgdGhlIHJpZ2h0IGFuc3dlcjogYSBjbG9zdXJlIHRoYXQgbmVlZHMgdG8gd2FpdCBsb25nZXIgdGhhblxuICogdGhpcyBzaG91bGQgbm90IGJlIHdhaXRpbmcgaW5zaWRlIE9ic2lkaWFuIGF0IGFsbC4gYHBvbGxJbk9ic2lkaWFuYCBpcyB0aGVcbiAqIHNhbmN0aW9uZWQgc2hhcGUgXHUyMDE0IHNob3J0IGNsb3N1cmVzLCB3aXRoIHRoZSB3YWl0aW5nIGRvbmUgZnJvbSBOb2RlIFx1MjAxNCBhbmQgaXRcbiAqIGV4aXN0cyBwcmVjaXNlbHkgc28gbm8gc2luZ2xlIGV2YWwgaXMgZXZlciBsb25nLlxuICpcbiAqIEJvdGggdHJhbnNwb3J0cyBkZWZhdWx0IHRvIHRoaXMgdmFsdWU6IGl0IGlzIHdoYXRcbiAqIGBPYnNpZGlhbkNkcFRyYW5zcG9ydE9wdGlvbnMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kc2AgYW5kXG4gKiBgT2JzaWRpYW5BbmRyb2lkQXBwaXVtVHJhbnNwb3J0T3B0aW9ucy5zY3JpcHRUaW1lb3V0SW5NaWxsaXNlY29uZHNgIGZhbGwgYmFja1xuICogdG8gd2hlbiB0aGV5IGFyZSBvbWl0dGVkLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9FVkFMX0NBUF9JTl9NSUxMSVNFQ09ORFMgPSAzMF8wMDA7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBMkNPLE1BQU0sbUNBQW1DOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* The per-eval cap: how long a single `evalInObsidian` closure may run before
|
|
5
|
+
* the transport carrying it gives up.
|
|
6
|
+
*
|
|
7
|
+
* It lives in its own module, and is re-exported from the package root, because
|
|
8
|
+
* it is the single most load-bearing number a test author has to respect — and
|
|
9
|
+
* until this module existed there was nothing to import. Both transports held
|
|
10
|
+
* the same 30s privately, so every consumer that needed to size a closure
|
|
11
|
+
* restated it as a literal with a comment saying where the number came from.
|
|
12
|
+
* That is a mirror nothing maintains: raise a cap here and every restatement is
|
|
13
|
+
* silently wrong in the direction that produces the unreadable failure, because
|
|
14
|
+
* the consumer goes on believing it has headroom it no longer has.
|
|
15
|
+
*
|
|
16
|
+
* **The two transports share this ONE constant rather than agreeing by
|
|
17
|
+
* coincidence.** They enforce it through different knobs — desktop bounds the
|
|
18
|
+
* `Runtime.evaluate` CDP command (`commandTimeoutInMilliseconds`), Android
|
|
19
|
+
* bounds the Execute Script call Node-side (`scriptTimeoutInMilliseconds`) —
|
|
20
|
+
* but the knobs are two implementations of one policy, not two policies that
|
|
21
|
+
* happen to agree. A reader of either default now sees which it is.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* The default per-eval cap, in milliseconds: the budget one `evalInObsidian`
|
|
25
|
+
* closure has to fit inside.
|
|
26
|
+
*
|
|
27
|
+
* Everything awaited inside a single closure shares this one budget — every
|
|
28
|
+
* `lib.waitUntil` timeout and every settle `sleep` — so a closure's declared
|
|
29
|
+
* waits have to sum to less than this, not merely be individually shorter.
|
|
30
|
+
*
|
|
31
|
+
* An overrun is reported as `EvalCapExceededError`, which names the cap, the
|
|
32
|
+
* transport that enforced it, and the option that sets it. Raising that option
|
|
33
|
+
* is almost never the right answer: a closure that needs to wait longer than
|
|
34
|
+
* this should not be waiting inside Obsidian at all. `pollInObsidian` is the
|
|
35
|
+
* sanctioned shape — short closures, with the waiting done from Node — and it
|
|
36
|
+
* exists precisely so no single eval is ever long.
|
|
37
|
+
*
|
|
38
|
+
* Both transports default to this value: it is what
|
|
39
|
+
* `ObsidianCdpTransportOptions.commandTimeoutInMilliseconds` and
|
|
40
|
+
* `ObsidianAndroidAppiumTransportOptions.scriptTimeoutInMilliseconds` fall back
|
|
41
|
+
* to when they are omitted.
|
|
42
|
+
*/
|
|
43
|
+
export declare const DEFAULT_EVAL_CAP_IN_MILLISECONDS = 30000;
|