@e2e-dev/web 0.11.0-canary-20260928184528
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/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +138 -0
- package/dist/.build.json +1 -0
- package/dist/actions.d.ts +23 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +174 -0
- package/dist/actions.js.map +1 -0
- package/dist/attempt-session.d.ts +77 -0
- package/dist/attempt-session.d.ts.map +1 -0
- package/dist/attempt-session.js +293 -0
- package/dist/attempt-session.js.map +1 -0
- package/dist/browser-connection.d.ts +34 -0
- package/dist/browser-connection.d.ts.map +1 -0
- package/dist/browser-connection.js +86 -0
- package/dist/browser-connection.js.map +1 -0
- package/dist/capture-scope.d.ts +21 -0
- package/dist/capture-scope.d.ts.map +1 -0
- package/dist/capture-scope.js +61 -0
- package/dist/capture-scope.js.map +1 -0
- package/dist/cdp-recovery.d.ts +29 -0
- package/dist/cdp-recovery.d.ts.map +1 -0
- package/dist/cdp-recovery.js +84 -0
- package/dist/cdp-recovery.js.map +1 -0
- package/dist/cdp-selectors.d.ts +15 -0
- package/dist/cdp-selectors.d.ts.map +1 -0
- package/dist/cdp-selectors.js +52 -0
- package/dist/cdp-selectors.js.map +1 -0
- package/dist/closed-shadow.d.ts +64 -0
- package/dist/closed-shadow.d.ts.map +1 -0
- package/dist/closed-shadow.js +142 -0
- package/dist/closed-shadow.js.map +1 -0
- package/dist/dialogs.d.ts +38 -0
- package/dist/dialogs.d.ts.map +1 -0
- package/dist/dialogs.js +87 -0
- package/dist/dialogs.js.map +1 -0
- package/dist/engine.d.ts +26 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +176 -0
- package/dist/engine.js.map +1 -0
- package/dist/evaluation.d.ts +18 -0
- package/dist/evaluation.d.ts.map +1 -0
- package/dist/evaluation.js +35 -0
- package/dist/evaluation.js.map +1 -0
- package/dist/in-page/read-semantics.d.ts +28 -0
- package/dist/in-page/read-semantics.d.ts.map +1 -0
- package/dist/in-page/read-semantics.js +1178 -0
- package/dist/in-page/read-semantics.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +40 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +117 -0
- package/dist/install.js.map +1 -0
- package/dist/label-selector.d.ts +37 -0
- package/dist/label-selector.d.ts.map +1 -0
- package/dist/label-selector.js +53 -0
- package/dist/label-selector.js.map +1 -0
- package/dist/locators.d.ts +76 -0
- package/dist/locators.d.ts.map +1 -0
- package/dist/locators.js +289 -0
- package/dist/locators.js.map +1 -0
- package/dist/observation-capture.d.ts +12 -0
- package/dist/observation-capture.d.ts.map +1 -0
- package/dist/observation-capture.js +93 -0
- package/dist/observation-capture.js.map +1 -0
- package/dist/observation.d.ts +63 -0
- package/dist/observation.d.ts.map +1 -0
- package/dist/observation.js +280 -0
- package/dist/observation.js.map +1 -0
- package/dist/observe.d.ts +51 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +105 -0
- package/dist/observe.js.map +1 -0
- package/dist/operation-budget.d.ts +11 -0
- package/dist/operation-budget.d.ts.map +1 -0
- package/dist/operation-budget.js +40 -0
- package/dist/operation-budget.js.map +1 -0
- package/dist/protected-app.d.ts +32 -0
- package/dist/protected-app.d.ts.map +1 -0
- package/dist/protected-app.js +39 -0
- package/dist/protected-app.js.map +1 -0
- package/dist/provider.d.ts +158 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +311 -0
- package/dist/provider.js.map +1 -0
- package/dist/read-node.d.ts +152 -0
- package/dist/read-node.d.ts.map +1 -0
- package/dist/read-node.js +42 -0
- package/dist/read-node.js.map +1 -0
- package/dist/refs.d.ts +43 -0
- package/dist/refs.d.ts.map +1 -0
- package/dist/refs.js +85 -0
- package/dist/refs.js.map +1 -0
- package/dist/route-pattern.d.ts +13 -0
- package/dist/route-pattern.d.ts.map +1 -0
- package/dist/route-pattern.js +55 -0
- package/dist/route-pattern.js.map +1 -0
- package/dist/selector-engines.d.ts +6 -0
- package/dist/selector-engines.d.ts.map +1 -0
- package/dist/selector-engines.js +8 -0
- package/dist/selector-engines.js.map +1 -0
- package/dist/support.d.ts +147 -0
- package/dist/support.d.ts.map +1 -0
- package/dist/support.js +366 -0
- package/dist/support.js.map +1 -0
- package/dist/surface.d.ts +313 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +691 -0
- package/dist/surface.js.map +1 -0
- package/dist/video.d.ts +59 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +116 -0
- package/dist/video.js.map +1 -0
- package/dist/web.d.ts +191 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +382 -0
- package/dist/web.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam a hosted browser service plugs into: a `BrowserProvider` leases a
|
|
3
|
+
* browser and hands back the CDP endpoint to attach to. In `worker` scope the
|
|
4
|
+
* engine leases one browser per worker slot in `prepare`, attaches each from
|
|
5
|
+
* its worker, and releases them all in `finish`; in `attempt` scope it leases
|
|
6
|
+
* a fresh browser in every `startAttempt` and releases it in `endAttempt`.
|
|
7
|
+
* Nothing here knows any vendor: a cloud browser service, a browser farm, or
|
|
8
|
+
* a Chrome on a machine down the hall are each one small provider in user code.
|
|
9
|
+
*/
|
|
10
|
+
import { type EngineAttemptContext, type EngineCleanupContext, type EngineFinishInfo, type EngineInitInfo, type EnginePrepareInfo, type EnginePrepareResult } from 'e2e/engine';
|
|
11
|
+
/**
|
|
12
|
+
* How long a lease lives. `worker` (the default) is one browser per worker
|
|
13
|
+
* slot, acquired in `prepare` and released in `finish`; `attempt` is a fresh
|
|
14
|
+
* browser per attempt, acquired in `startAttempt` and released in
|
|
15
|
+
* `endAttempt`, reconnected through the lease's `reconnectEndpoint` after a
|
|
16
|
+
* transport drop.
|
|
17
|
+
*/
|
|
18
|
+
export type BrowserProviderScope = 'worker' | 'attempt';
|
|
19
|
+
/** What the engine asks a provider for: one browser for one worker slot, or for one attempt, of a run. */
|
|
20
|
+
export interface BrowserRequest {
|
|
21
|
+
/** The run id, for naming the session at the provider. */
|
|
22
|
+
readonly runId: string;
|
|
23
|
+
/** The target the browser serves. */
|
|
24
|
+
readonly targetName: string;
|
|
25
|
+
/** Worker slot the browser serves, `0` to `slots - 1`; in `worker` scope `slots` leases are acquired at once. */
|
|
26
|
+
readonly slot: number;
|
|
27
|
+
/** Worker slots the run uses for this target, in all. */
|
|
28
|
+
readonly slots: number;
|
|
29
|
+
/** Present only for a per-attempt lease. */
|
|
30
|
+
readonly attemptId?: string | undefined;
|
|
31
|
+
/** The run's environment: where a provider reads its token from, never `process.env`. */
|
|
32
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
33
|
+
/** Aborts on interrupt, and when the attempt that needs the browser is cancelled or exceeds its budget. */
|
|
34
|
+
readonly signal: AbortSignal;
|
|
35
|
+
/** Reports one line of progress to the run's reporter (a session URL to watch); discarded in a worker process. */
|
|
36
|
+
readonly log: (line: string) => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One leased browser, as `acquire` returns it and `release` gets it back.
|
|
40
|
+
* JSON data only: a lease travels from the runner process to the worker that
|
|
41
|
+
* attaches to it through the environment.
|
|
42
|
+
*/
|
|
43
|
+
export interface BrowserLease {
|
|
44
|
+
/**
|
|
45
|
+
* The provider's handle on the lease (a session id); named in progress
|
|
46
|
+
* lines and handed back to `release`. A provider may keep further fields on
|
|
47
|
+
* the object it returns: `release` gets that same object, while only the
|
|
48
|
+
* fields declared here travel to the worker.
|
|
49
|
+
*/
|
|
50
|
+
readonly id: string;
|
|
51
|
+
/** `ws://`, `wss://`, or `http://` DevTools endpoint to attach to over CDP. */
|
|
52
|
+
readonly cdpEndpoint: string;
|
|
53
|
+
/**
|
|
54
|
+
* Endpoint to reattach to the same browser after a transport drop, when it
|
|
55
|
+
* differs from `cdpEndpoint`; only meaningful for a per-attempt lease.
|
|
56
|
+
*/
|
|
57
|
+
readonly reconnectEndpoint?: string | undefined;
|
|
58
|
+
}
|
|
59
|
+
/** Handed to `release`, once per lease. */
|
|
60
|
+
export interface BrowserReleaseContext {
|
|
61
|
+
readonly runId: string;
|
|
62
|
+
readonly targetName: string;
|
|
63
|
+
/** The run's environment, the same `acquire` saw. */
|
|
64
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
65
|
+
/** Aborts when the cleanup budget is spent. */
|
|
66
|
+
readonly signal: AbortSignal;
|
|
67
|
+
readonly log: (line: string) => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A source of hosted browsers. In `worker` scope `acquire` is called once per
|
|
71
|
+
* worker slot, for every slot at once, in the runner process; a worker whose
|
|
72
|
+
* browser drops calls it again, from its own process, for a replacement. In
|
|
73
|
+
* `attempt` scope every `startAttempt` calls it from the worker. `release`
|
|
74
|
+
* is called exactly once per lease, by the process that acquired it, also
|
|
75
|
+
* after an `acquire` of another slot failed. A provider must not rely on
|
|
76
|
+
* runner-process state to serve a request from a worker.
|
|
77
|
+
*/
|
|
78
|
+
export interface BrowserProvider {
|
|
79
|
+
/** Label in progress lines and error messages. */
|
|
80
|
+
readonly name: string;
|
|
81
|
+
/** How long a lease lives; `worker` when absent. */
|
|
82
|
+
readonly scope?: BrowserProviderScope | undefined;
|
|
83
|
+
acquire(request: BrowserRequest): Promise<BrowserLease>;
|
|
84
|
+
release(lease: BrowserLease, context: BrowserReleaseContext): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
/** Narrows an intended provider, or names what it is missing. */
|
|
87
|
+
export declare function asBrowserProvider(browser: object): BrowserProvider;
|
|
88
|
+
/**
|
|
89
|
+
* Browsers a provider leases for one target, on both sides of the worker
|
|
90
|
+
* boundary. In the runner, `prepare` leases one per slot, all at once (hosted
|
|
91
|
+
* browsers start in parallel and are billed from the moment they do), and
|
|
92
|
+
* holds every lease granted for `finish` before the outcome is known, so a
|
|
93
|
+
* slot that fails to lease fails the run and the others are still released.
|
|
94
|
+
* In a worker, `init` reads the slot's lease from the environment; a browser
|
|
95
|
+
* that drops is replaced by a lease the worker acquires itself, and
|
|
96
|
+
* per-attempt leases come and go with the attempt. Each lease is released
|
|
97
|
+
* exactly once, by the side that acquired it.
|
|
98
|
+
*/
|
|
99
|
+
export declare class LeasedBrowsers {
|
|
100
|
+
private readonly provider;
|
|
101
|
+
readonly scope: BrowserProviderScope;
|
|
102
|
+
/** Leases granted so far, per target, filled as each `acquire` settles. */
|
|
103
|
+
private readonly held;
|
|
104
|
+
private run;
|
|
105
|
+
/** The lease the worker's shared browser attaches to, and whether `endpoint` has handed it out yet. */
|
|
106
|
+
private current;
|
|
107
|
+
private attached;
|
|
108
|
+
private attempt;
|
|
109
|
+
/** The attempt whose lease is being acquired or held; a lease that arrives for any other attempt is released, not committed. */
|
|
110
|
+
private opened;
|
|
111
|
+
/** This worker's tenure, replaced by `init` and `dispose`; a replacement lease that arrives for an earlier one is released, not committed. */
|
|
112
|
+
private tenure;
|
|
113
|
+
constructor(provider: BrowserProvider);
|
|
114
|
+
/**
|
|
115
|
+
* Leases one browser per worker slot the run will use, in `worker` scope,
|
|
116
|
+
* and hands the leases to the workers through the environment; `attempt`
|
|
117
|
+
* scope leases per attempt instead and hands over the slot count alone. A
|
|
118
|
+
* target nothing runs on leases nothing.
|
|
119
|
+
*/
|
|
120
|
+
prepare(info: EnginePrepareInfo): Promise<EnginePrepareResult>;
|
|
121
|
+
/** Releases what `prepare` leased for the target, every lease before the first failure is reported. */
|
|
122
|
+
finish(info: EngineFinishInfo): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Records the run this worker serves and, in `worker` scope, the lease its
|
|
125
|
+
* slot was handed. A missing hand-off is a broken invariant: the runner
|
|
126
|
+
* prepares every target before it starts a worker, and caps the slots at
|
|
127
|
+
* the workers `prepare` reported.
|
|
128
|
+
*/
|
|
129
|
+
init(info: EngineInitInfo): void;
|
|
130
|
+
/**
|
|
131
|
+
* The endpoint the worker's shared browser attaches to, in `worker` scope:
|
|
132
|
+
* the slot's lease the first time, and a replacement the worker leases
|
|
133
|
+
* itself every time after, since the connection only asks again once the
|
|
134
|
+
* browser it had dropped. A dead lease is released by the side that
|
|
135
|
+
* acquired it: the worker here, best effort, or the runner in `finish`. A
|
|
136
|
+
* replacement that arrives once the attempt was cancelled or the worker
|
|
137
|
+
* disposed is given straight back and never committed.
|
|
138
|
+
*/
|
|
139
|
+
endpoint(signal: AbortSignal): Promise<string>;
|
|
140
|
+
/**
|
|
141
|
+
* Leases a fresh browser for the attempt, in `attempt` scope; `endAttempt`
|
|
142
|
+
* releases it on every path. A lease that arrives once the attempt was
|
|
143
|
+
* cancelled or already ended (a provider that ignored the abort) is given
|
|
144
|
+
* straight back and never committed, so a retry never finds it.
|
|
145
|
+
*/
|
|
146
|
+
startAttempt(context: EngineAttemptContext): Promise<BrowserLease>;
|
|
147
|
+
/** Releases the attempt's lease, when one was granted; idempotent, and safe after a failed `startAttempt`. */
|
|
148
|
+
endAttempt(context: EngineCleanupContext): Promise<void>;
|
|
149
|
+
/** Releases the replacement lease the worker acquired for itself; what `prepare` leased is the runner's to release. */
|
|
150
|
+
dispose(context: EngineCleanupContext): Promise<void>;
|
|
151
|
+
private requireRun;
|
|
152
|
+
/** One `acquire`, its result checked field by field; a failure is named after the provider. */
|
|
153
|
+
private acquire;
|
|
154
|
+
/** One `release` from the worker, bounded by the cleanup budget; a failure is a cleanup error named after the provider. */
|
|
155
|
+
private release;
|
|
156
|
+
private releaseContext;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam a hosted browser service plugs into: a `BrowserProvider` leases a
|
|
3
|
+
* browser and hands back the CDP endpoint to attach to. In `worker` scope the
|
|
4
|
+
* engine leases one browser per worker slot in `prepare`, attaches each from
|
|
5
|
+
* its worker, and releases them all in `finish`; in `attempt` scope it leases
|
|
6
|
+
* a fresh browser in every `startAttempt` and releases it in `endAttempt`.
|
|
7
|
+
* Nothing here knows any vendor: a cloud browser service, a browser farm, or
|
|
8
|
+
* a Chrome on a machine down the hall are each one small provider in user code.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from 'node:crypto';
|
|
11
|
+
import { ConfigurationError, EngineError, obj, raceAbort, } from 'e2e/engine';
|
|
12
|
+
import { message } from './support.js';
|
|
13
|
+
const SCOPES = new Set(['worker', 'attempt']);
|
|
14
|
+
/** Narrows an intended provider, or names what it is missing. */
|
|
15
|
+
export function asBrowserProvider(browser) {
|
|
16
|
+
const candidate = browser;
|
|
17
|
+
if (typeof candidate.name !== 'string' || candidate.name.trim() === '') {
|
|
18
|
+
throw new ConfigurationError('INVALID_CONFIG', 'web: a `browser` provider needs a non-empty `name`');
|
|
19
|
+
}
|
|
20
|
+
for (const member of ['acquire', 'release']) {
|
|
21
|
+
if (typeof candidate[member] !== 'function') {
|
|
22
|
+
throw new ConfigurationError('INVALID_CONFIG', `web: browser provider "${candidate.name}" must implement ${member}()`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (candidate.scope !== undefined && (typeof candidate.scope !== 'string' || !SCOPES.has(candidate.scope))) {
|
|
26
|
+
throw new ConfigurationError('INVALID_CONFIG', `web: browser provider "${candidate.name}" has scope ${JSON.stringify(candidate.scope)}; use "worker" or "attempt"`);
|
|
27
|
+
}
|
|
28
|
+
return browser;
|
|
29
|
+
}
|
|
30
|
+
function isNonEmptyString(value) {
|
|
31
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
32
|
+
}
|
|
33
|
+
/** A lease as a provider returned it or as JSON parsed it back, checked field by field: the engine trusts nothing it did not write. */
|
|
34
|
+
function isBrowserLease(value) {
|
|
35
|
+
if (typeof value !== 'object' || value === null)
|
|
36
|
+
return false;
|
|
37
|
+
const { id, cdpEndpoint, reconnectEndpoint } = value;
|
|
38
|
+
return isNonEmptyString(id) && isNonEmptyString(cdpEndpoint) && (reconnectEndpoint === undefined || isNonEmptyString(reconnectEndpoint));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The most the serialized hand-off of one target may occupy in a worker's
|
|
42
|
+
* environment: a lease comes from third-party code, and an oversized
|
|
43
|
+
* environment fails the worker spawn with an opaque error.
|
|
44
|
+
*/
|
|
45
|
+
const MAX_HANDOFF_ENV_BYTES = 16 * 1024;
|
|
46
|
+
/**
|
|
47
|
+
* The environment variable a target's hand-off travels to the workers in:
|
|
48
|
+
* the name made environment-safe for reading, plus a digest of the exact
|
|
49
|
+
* name so `web-a` and `web.a` never share a key.
|
|
50
|
+
*/
|
|
51
|
+
function handoffVariable(targetName) {
|
|
52
|
+
const readable = targetName.replace(/[^A-Za-z0-9]/g, '_').toUpperCase();
|
|
53
|
+
const digest = createHash('sha256').update(targetName).digest('hex').slice(0, 8).toUpperCase();
|
|
54
|
+
return `E2E_WEB_BROWSERS_${readable}_${digest}`;
|
|
55
|
+
}
|
|
56
|
+
/** Serializes the hand-off for the environment: declared lease fields only, bounded. */
|
|
57
|
+
function encodeHandoff(handoff) {
|
|
58
|
+
const encoded = JSON.stringify({
|
|
59
|
+
slots: handoff.slots,
|
|
60
|
+
leases: handoff.leases.map((lease) => obj({ id: lease.id, cdpEndpoint: lease.cdpEndpoint, reconnectEndpoint: lease.reconnectEndpoint })),
|
|
61
|
+
});
|
|
62
|
+
const bytes = Buffer.byteLength(encoded);
|
|
63
|
+
if (bytes > MAX_HANDOFF_ENV_BYTES) {
|
|
64
|
+
throw new EngineError('ENGINE_FAILURE', `the browser leases take ${bytes} bytes; the worker environment carries at most ${MAX_HANDOFF_ENV_BYTES}`, { retryable: false });
|
|
65
|
+
}
|
|
66
|
+
return encoded;
|
|
67
|
+
}
|
|
68
|
+
/** The hand-off a `prepare` left in the environment, or `undefined` when there is none it can read. */
|
|
69
|
+
function decodeHandoff(raw) {
|
|
70
|
+
if (raw === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(raw);
|
|
74
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
75
|
+
return undefined;
|
|
76
|
+
const { slots, leases } = parsed;
|
|
77
|
+
if (Number.isInteger(slots) && slots >= 0 && Array.isArray(leases) && leases.every(isBrowserLease)) {
|
|
78
|
+
return { slots: slots, leases };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Not ours to read.
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
/** Runs every task, then reports the first failure: nothing is skipped because a sibling failed. */
|
|
87
|
+
async function allOrFirstFailure(tasks, describe) {
|
|
88
|
+
// `async` so a task that throws before its first await is a rejection like any other, not an escape.
|
|
89
|
+
const settled = await Promise.allSettled(tasks.map(async (task) => task()));
|
|
90
|
+
const failed = settled.find((result) => result.status === 'rejected');
|
|
91
|
+
if (failed !== undefined) {
|
|
92
|
+
if (failed.reason instanceof EngineError)
|
|
93
|
+
throw failed.reason;
|
|
94
|
+
throw new EngineError('ENGINE_FAILURE', `${describe}: ${message(failed.reason)}`, { retryable: false, cause: failed.reason });
|
|
95
|
+
}
|
|
96
|
+
return settled.flatMap((result) => (result.status === 'fulfilled' ? [result.value] : []));
|
|
97
|
+
}
|
|
98
|
+
const discard = () => undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Browsers a provider leases for one target, on both sides of the worker
|
|
101
|
+
* boundary. In the runner, `prepare` leases one per slot, all at once (hosted
|
|
102
|
+
* browsers start in parallel and are billed from the moment they do), and
|
|
103
|
+
* holds every lease granted for `finish` before the outcome is known, so a
|
|
104
|
+
* slot that fails to lease fails the run and the others are still released.
|
|
105
|
+
* In a worker, `init` reads the slot's lease from the environment; a browser
|
|
106
|
+
* that drops is replaced by a lease the worker acquires itself, and
|
|
107
|
+
* per-attempt leases come and go with the attempt. Each lease is released
|
|
108
|
+
* exactly once, by the side that acquired it.
|
|
109
|
+
*/
|
|
110
|
+
export class LeasedBrowsers {
|
|
111
|
+
provider;
|
|
112
|
+
scope;
|
|
113
|
+
/** Leases granted so far, per target, filled as each `acquire` settles. */
|
|
114
|
+
held = new Map();
|
|
115
|
+
run;
|
|
116
|
+
/** The lease the worker's shared browser attaches to, and whether `endpoint` has handed it out yet. */
|
|
117
|
+
current;
|
|
118
|
+
attached = false;
|
|
119
|
+
attempt;
|
|
120
|
+
/** The attempt whose lease is being acquired or held; a lease that arrives for any other attempt is released, not committed. */
|
|
121
|
+
opened;
|
|
122
|
+
/** This worker's tenure, replaced by `init` and `dispose`; a replacement lease that arrives for an earlier one is released, not committed. */
|
|
123
|
+
tenure = {};
|
|
124
|
+
constructor(provider) {
|
|
125
|
+
this.provider = provider;
|
|
126
|
+
this.scope = provider.scope ?? 'worker';
|
|
127
|
+
}
|
|
128
|
+
// --- runner side ---
|
|
129
|
+
/**
|
|
130
|
+
* Leases one browser per worker slot the run will use, in `worker` scope,
|
|
131
|
+
* and hands the leases to the workers through the environment; `attempt`
|
|
132
|
+
* scope leases per attempt instead and hands over the slot count alone. A
|
|
133
|
+
* target nothing runs on leases nothing.
|
|
134
|
+
*/
|
|
135
|
+
async prepare(info) {
|
|
136
|
+
if (info.slots === 0)
|
|
137
|
+
return {};
|
|
138
|
+
const variable = handoffVariable(info.targetName);
|
|
139
|
+
if (this.scope === 'attempt')
|
|
140
|
+
return { env: { [variable]: encodeHandoff({ slots: info.slots, leases: [] }) } };
|
|
141
|
+
const { provider } = this;
|
|
142
|
+
const held = [];
|
|
143
|
+
this.held.set(info.targetName, held);
|
|
144
|
+
info.log(`leasing ${info.slots} browser(s) from ${provider.name}`);
|
|
145
|
+
const leases = await allOrFirstFailure(Array.from({ length: info.slots }, (_, slot) => async () => {
|
|
146
|
+
const lease = await this.acquire({
|
|
147
|
+
runId: info.runId,
|
|
148
|
+
targetName: info.targetName,
|
|
149
|
+
slot,
|
|
150
|
+
slots: info.slots,
|
|
151
|
+
env: info.env,
|
|
152
|
+
signal: info.signal,
|
|
153
|
+
log: (line) => info.log(`${provider.name} (${slot + 1} of ${info.slots}): ${line}`),
|
|
154
|
+
});
|
|
155
|
+
held.push(lease);
|
|
156
|
+
info.log(`${provider.name}: leased ${lease.id}`);
|
|
157
|
+
return lease;
|
|
158
|
+
}), `browser provider "${provider.name}" could not lease a browser`);
|
|
159
|
+
return { workers: leases.length, env: { [variable]: encodeHandoff({ slots: leases.length, leases }) } };
|
|
160
|
+
}
|
|
161
|
+
/** Releases what `prepare` leased for the target, every lease before the first failure is reported. */
|
|
162
|
+
async finish(info) {
|
|
163
|
+
const { provider } = this;
|
|
164
|
+
const leases = this.held.get(info.targetName);
|
|
165
|
+
this.held.delete(info.targetName);
|
|
166
|
+
if (leases === undefined || leases.length === 0)
|
|
167
|
+
return;
|
|
168
|
+
const context = { runId: info.runId, targetName: info.targetName, env: info.env, signal: info.signal, log: (line) => info.log(`${provider.name}: ${line}`) };
|
|
169
|
+
await allOrFirstFailure(leases.map((lease) => () => provider.release(lease, context)), `browser provider "${provider.name}" could not release a browser`);
|
|
170
|
+
info.log(`${provider.name}: released ${leases.length} browser(s)`);
|
|
171
|
+
}
|
|
172
|
+
// --- worker side ---
|
|
173
|
+
/**
|
|
174
|
+
* Records the run this worker serves and, in `worker` scope, the lease its
|
|
175
|
+
* slot was handed. A missing hand-off is a broken invariant: the runner
|
|
176
|
+
* prepares every target before it starts a worker, and caps the slots at
|
|
177
|
+
* the workers `prepare` reported.
|
|
178
|
+
*/
|
|
179
|
+
init(info) {
|
|
180
|
+
const { provider } = this;
|
|
181
|
+
this.current = undefined;
|
|
182
|
+
this.attached = false;
|
|
183
|
+
this.tenure = {};
|
|
184
|
+
const handoff = decodeHandoff(info.env[handoffVariable(info.targetName)]);
|
|
185
|
+
if (handoff === undefined) {
|
|
186
|
+
throw new EngineError('ENGINE_FAILURE', `browser provider "${provider.name}" prepared nothing for target "${info.targetName}"; the runner must prepare the target before a worker starts`, { retryable: false });
|
|
187
|
+
}
|
|
188
|
+
this.run = { runId: info.runId, targetName: info.targetName, env: info.env, slot: info.workerSlot, slots: handoff.slots };
|
|
189
|
+
if (this.scope === 'attempt')
|
|
190
|
+
return;
|
|
191
|
+
const lease = handoff.leases[info.workerSlot];
|
|
192
|
+
if (lease === undefined) {
|
|
193
|
+
throw new EngineError('ENGINE_FAILURE', `worker slot ${info.workerSlot} is outside the ${handoff.leases.length} browser(s) "${provider.name}" leased; the runner must cap the target at the engine's reported workers`, { retryable: false });
|
|
194
|
+
}
|
|
195
|
+
this.current = { lease, owned: false };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* The endpoint the worker's shared browser attaches to, in `worker` scope:
|
|
199
|
+
* the slot's lease the first time, and a replacement the worker leases
|
|
200
|
+
* itself every time after, since the connection only asks again once the
|
|
201
|
+
* browser it had dropped. A dead lease is released by the side that
|
|
202
|
+
* acquired it: the worker here, best effort, or the runner in `finish`. A
|
|
203
|
+
* replacement that arrives once the attempt was cancelled or the worker
|
|
204
|
+
* disposed is given straight back and never committed.
|
|
205
|
+
*/
|
|
206
|
+
async endpoint(signal) {
|
|
207
|
+
const run = this.requireRun();
|
|
208
|
+
const previous = this.current;
|
|
209
|
+
if (previous !== undefined && !this.attached) {
|
|
210
|
+
this.attached = true;
|
|
211
|
+
return previous.lease.cdpEndpoint;
|
|
212
|
+
}
|
|
213
|
+
const { tenure } = this;
|
|
214
|
+
const lease = await this.acquire({ runId: run.runId, targetName: run.targetName, slot: run.slot, slots: run.slots, env: run.env, signal, log: discard });
|
|
215
|
+
if (signal.aborted || this.tenure !== tenure) {
|
|
216
|
+
await this.provider.release(lease, this.releaseContext(run, signal)).catch(discard);
|
|
217
|
+
throw new EngineError('CANCELLED', `browser lease from "${this.provider.name}" arrived after the worker gave up; released`, { retryable: false });
|
|
218
|
+
}
|
|
219
|
+
this.current = { lease, owned: true };
|
|
220
|
+
this.attached = true;
|
|
221
|
+
if (previous?.owned === true)
|
|
222
|
+
await this.provider.release(previous.lease, this.releaseContext(run, signal)).catch(discard);
|
|
223
|
+
return lease.cdpEndpoint;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Leases a fresh browser for the attempt, in `attempt` scope; `endAttempt`
|
|
227
|
+
* releases it on every path. A lease that arrives once the attempt was
|
|
228
|
+
* cancelled or already ended (a provider that ignored the abort) is given
|
|
229
|
+
* straight back and never committed, so a retry never finds it.
|
|
230
|
+
*/
|
|
231
|
+
async startAttempt(context) {
|
|
232
|
+
const run = this.requireRun();
|
|
233
|
+
const opened = {};
|
|
234
|
+
this.opened = opened;
|
|
235
|
+
const lease = await this.acquire({
|
|
236
|
+
runId: run.runId,
|
|
237
|
+
targetName: run.targetName,
|
|
238
|
+
slot: run.slot,
|
|
239
|
+
slots: run.slots,
|
|
240
|
+
attemptId: context.attemptId,
|
|
241
|
+
env: run.env,
|
|
242
|
+
signal: context.signal,
|
|
243
|
+
log: discard,
|
|
244
|
+
});
|
|
245
|
+
if (context.signal.aborted || this.opened !== opened) {
|
|
246
|
+
await this.provider.release(lease, this.releaseContext(run, context.signal)).catch(discard);
|
|
247
|
+
throw new EngineError('CANCELLED', `browser lease from "${this.provider.name}" arrived after the attempt ended; released`, { retryable: false });
|
|
248
|
+
}
|
|
249
|
+
this.attempt = lease;
|
|
250
|
+
return lease;
|
|
251
|
+
}
|
|
252
|
+
/** Releases the attempt's lease, when one was granted; idempotent, and safe after a failed `startAttempt`. */
|
|
253
|
+
async endAttempt(context) {
|
|
254
|
+
const lease = this.attempt;
|
|
255
|
+
this.attempt = undefined;
|
|
256
|
+
this.opened = undefined;
|
|
257
|
+
if (lease === undefined)
|
|
258
|
+
return;
|
|
259
|
+
await this.release(lease, context);
|
|
260
|
+
}
|
|
261
|
+
/** Releases the replacement lease the worker acquired for itself; what `prepare` leased is the runner's to release. */
|
|
262
|
+
async dispose(context) {
|
|
263
|
+
const current = this.current;
|
|
264
|
+
this.current = undefined;
|
|
265
|
+
this.attached = false;
|
|
266
|
+
this.tenure = {};
|
|
267
|
+
if (current === undefined || !current.owned)
|
|
268
|
+
return;
|
|
269
|
+
await this.release(current.lease, context);
|
|
270
|
+
}
|
|
271
|
+
requireRun() {
|
|
272
|
+
if (this.run === undefined) {
|
|
273
|
+
throw new EngineError('ENGINE_FAILURE', `browser provider "${this.provider.name}" was asked for a browser before init`, { retryable: false });
|
|
274
|
+
}
|
|
275
|
+
return this.run;
|
|
276
|
+
}
|
|
277
|
+
/** One `acquire`, its result checked field by field; a failure is named after the provider. */
|
|
278
|
+
async acquire(request) {
|
|
279
|
+
const { provider } = this;
|
|
280
|
+
let lease;
|
|
281
|
+
try {
|
|
282
|
+
lease = await provider.acquire(request);
|
|
283
|
+
}
|
|
284
|
+
catch (cause) {
|
|
285
|
+
if (request.signal.aborted) {
|
|
286
|
+
throw new EngineError('CANCELLED', `browser lease from "${provider.name}" cancelled`, { retryable: false, cause });
|
|
287
|
+
}
|
|
288
|
+
throw new EngineError('ENGINE_FAILURE', `browser provider "${provider.name}" could not lease a browser: ${message(cause)}`, { retryable: false, cause });
|
|
289
|
+
}
|
|
290
|
+
if (!isBrowserLease(lease)) {
|
|
291
|
+
throw new EngineError('ENGINE_FAILURE', `browser provider "${provider.name}" returned a lease without an id and a cdpEndpoint`, { retryable: false });
|
|
292
|
+
}
|
|
293
|
+
return lease;
|
|
294
|
+
}
|
|
295
|
+
/** One `release` from the worker, bounded by the cleanup budget; a failure is a cleanup error named after the provider. */
|
|
296
|
+
async release(lease, budget) {
|
|
297
|
+
const run = this.requireRun();
|
|
298
|
+
try {
|
|
299
|
+
await raceAbort(this.provider.release(lease, this.releaseContext(run, budget.signal)), budget.signal, `releasing browser ${lease.id}`);
|
|
300
|
+
}
|
|
301
|
+
catch (cause) {
|
|
302
|
+
if (cause instanceof EngineError)
|
|
303
|
+
throw cause;
|
|
304
|
+
throw new EngineError('ENGINE_FAILURE', `browser provider "${this.provider.name}" could not release browser ${lease.id}: ${message(cause)}`, { retryable: false, cause });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
releaseContext(run, signal) {
|
|
308
|
+
return { runId: run.runId, targetName: run.targetName, env: run.env, signal, log: discard };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire types of the in-page semantic reader and the page functions
|
|
3
|
+
* assembled from its source for locator.evaluate, locator.evaluateAll, and
|
|
4
|
+
* page.evaluate. The reader itself lives in `in-page/read-semantics.ts`; it is
|
|
5
|
+
* serialized into the page, so every page function here is built from its
|
|
6
|
+
* source with `new Function` and stays free of module-scope captures.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The one definition of a secure field.
|
|
10
|
+
*
|
|
11
|
+
* It is a selector rather than a predicate because it has to be applied from
|
|
12
|
+
* two sides that cannot share code: the in-page reader matches elements
|
|
13
|
+
* against it to mark nodes `secure`, and the engine hands the same string to
|
|
14
|
+
* the screenshot masker. One string means the tree's redaction and the image's
|
|
15
|
+
* redaction cannot describe different sets of elements, which is what the
|
|
16
|
+
* runner's pixel-clearance check relies on.
|
|
17
|
+
*/
|
|
18
|
+
export declare const SECURE_FIELD_SELECTOR = "input[type=\"password\" i]";
|
|
19
|
+
export interface RawNodeData {
|
|
20
|
+
role: string | null;
|
|
21
|
+
name: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Every label a person or a tool may call this control by: its `aria-label`,
|
|
24
|
+
* each `aria-labelledby` target, and each associated `<label>`, read as an
|
|
25
|
+
* accessible name (aria-hidden dropped). Null for a node with none. An exact
|
|
26
|
+
* label query matches any one of them, as Playwright's `getByLabel` does,
|
|
27
|
+
* rather than the combined or overridden `name`.
|
|
28
|
+
*/
|
|
29
|
+
labels: string[] | null;
|
|
30
|
+
text: string | null;
|
|
31
|
+
value: string | null;
|
|
32
|
+
/** Text selected inside the focused field or editing host; null when unfocused, collapsed, or secure. */
|
|
33
|
+
selection: string | null;
|
|
34
|
+
inputPurpose: 'username' | 'password' | 'one-time-code' | 'generic-secret' | 'none';
|
|
35
|
+
states: {
|
|
36
|
+
checked: boolean | null;
|
|
37
|
+
disabled: boolean;
|
|
38
|
+
selected: boolean | null;
|
|
39
|
+
expanded: boolean | null;
|
|
40
|
+
pressed: boolean | null;
|
|
41
|
+
focused: boolean;
|
|
42
|
+
hidden: boolean;
|
|
43
|
+
secure: boolean;
|
|
44
|
+
};
|
|
45
|
+
/** Heading level of a heading: `aria-level`, else the digit of `h1` through `h6`; null for anything else. */
|
|
46
|
+
level: number | null;
|
|
47
|
+
attributes: Record<string, string>;
|
|
48
|
+
/** Value of the project's test-id attribute, when the element carries one. */
|
|
49
|
+
testId: string | null;
|
|
50
|
+
rect: {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** One observed node plus its position in the flattened depth-first tree. */
|
|
58
|
+
export interface RawObservedNode extends RawNodeData {
|
|
59
|
+
/** Index of the nearest included ancestor, or -1 for the root. */
|
|
60
|
+
parent: number;
|
|
61
|
+
/** Unique CSS selector of this `<iframe>` element; set only for iframes. */
|
|
62
|
+
frameSelector?: string;
|
|
63
|
+
}
|
|
64
|
+
/** One walked document. */
|
|
65
|
+
interface RawObservation {
|
|
66
|
+
nodes: RawObservedNode[];
|
|
67
|
+
/** True when the node budget stopped the walk before the document was read whole. */
|
|
68
|
+
truncated: boolean;
|
|
69
|
+
/** Live element handles positionally aligned with `nodes`. */
|
|
70
|
+
elements: Element[];
|
|
71
|
+
/**
|
|
72
|
+
* Node ids positionally aligned with `nodes`. An id is stamped on the element
|
|
73
|
+
* the first time an observation includes it and read back on every later
|
|
74
|
+
* one, so the same element keeps the same id for as long as it lives in the
|
|
75
|
+
* document: two looks at an unchanged screen name its nodes identically, and
|
|
76
|
+
* an update can list exactly what changed. A re-created element (a framework
|
|
77
|
+
* re-mount, a new document) is a new node and gets a fresh id.
|
|
78
|
+
*/
|
|
79
|
+
ids: string[];
|
|
80
|
+
}
|
|
81
|
+
export type SemanticMode = {
|
|
82
|
+
kind: 'node';
|
|
83
|
+
} | {
|
|
84
|
+
kind: 'tree';
|
|
85
|
+
maxNodes: number;
|
|
86
|
+
/**
|
|
87
|
+
* First numeric id available to nodes seen for the first time. The caller
|
|
88
|
+
* reserves maxNodes ids before execution, so an abandoned reader cannot
|
|
89
|
+
* collide with later captures or locator resolution.
|
|
90
|
+
*/
|
|
91
|
+
idSeed: number;
|
|
92
|
+
/** Cuts each node's name at this length; the caller owns the contract value. */
|
|
93
|
+
nameLimit: number;
|
|
94
|
+
/** Cuts each node's text at this length; the caller owns the contract value. */
|
|
95
|
+
textLimit: number;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* What a node read reports for an element no longer in its document. A
|
|
99
|
+
* detached element has no boxes, so everything else it would report (hidden,
|
|
100
|
+
* no labels) describes nothing on screen; its current value is still its own.
|
|
101
|
+
*/
|
|
102
|
+
export interface DetachedNodeData {
|
|
103
|
+
readonly detached: true;
|
|
104
|
+
readonly value: string | null;
|
|
105
|
+
}
|
|
106
|
+
/** Result of one read, selected by the mode discriminant. */
|
|
107
|
+
export type SemanticResult<Mode extends SemanticMode> = Mode extends {
|
|
108
|
+
kind: 'node';
|
|
109
|
+
} ? RawNodeData | DetachedNodeData : RawObservation;
|
|
110
|
+
/** Options for a single-node read, shared by `evaluate` and `evaluateAll` callers. */
|
|
111
|
+
interface NodeReadOptions {
|
|
112
|
+
readonly testIdAttribute: string;
|
|
113
|
+
readonly secureFieldSelector: string;
|
|
114
|
+
readonly mode: {
|
|
115
|
+
readonly kind: 'node';
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Options for one document's tree walk. */
|
|
119
|
+
interface TreeReadOptions {
|
|
120
|
+
readonly testIdAttribute: string;
|
|
121
|
+
readonly secureFieldSelector: string;
|
|
122
|
+
readonly mode: Extract<SemanticMode, {
|
|
123
|
+
kind: 'tree';
|
|
124
|
+
}>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Walks a whole document from its root element in one in-page call. Built
|
|
128
|
+
* from the reader's source like the batch reader below, so the caller
|
|
129
|
+
* evaluates it directly on a page or frame instead of first resolving a
|
|
130
|
+
* `:root` locator - one fewer protocol round trip per document per capture.
|
|
131
|
+
*/
|
|
132
|
+
export declare const readDocumentSemanticsFunction: (options: TreeReadOptions) => RawObservation;
|
|
133
|
+
/**
|
|
134
|
+
* Reads every matched element in one in-page round trip. A page function
|
|
135
|
+
* cannot close over module scope, so the batch function is assembled from the
|
|
136
|
+
* reader's own source (the same source `evaluate` sends) and is a
|
|
137
|
+
* self-contained function Playwright serializes and calls with the elements.
|
|
138
|
+
*/
|
|
139
|
+
export declare const readManySemanticsFunction: (elements: Element[], options: NodeReadOptions) => (RawNodeData | DetachedNodeData)[];
|
|
140
|
+
/**
|
|
141
|
+
* Reads every handle the caller already holds in one round trip, so what is
|
|
142
|
+
* read and what is later acted on are the same elements by construction rather
|
|
143
|
+
* than by a second lookup. Evaluated on the first handle so the read runs in
|
|
144
|
+
* the frame the handles belong to; `page.evaluate` would reject handles taken
|
|
145
|
+
* inside an iframe.
|
|
146
|
+
*/
|
|
147
|
+
export declare const readHandlesSemanticsFunction: (first: Element, arg: {
|
|
148
|
+
elements: Element[];
|
|
149
|
+
options: NodeReadOptions;
|
|
150
|
+
}) => (RawNodeData | DetachedNodeData)[];
|
|
151
|
+
export {};
|
|
152
|
+
//# sourceMappingURL=read-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-node.d.ts","sourceRoot":"","sources":["../src/read-node.ts"],"names":[],"mappings":"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"}
|