@juxtapose/core 0.4.0 → 0.5.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.
Files changed (131) hide show
  1. package/dist/agent/handoff.d.ts +8 -1
  2. package/dist/agent/handoff.js +75 -7
  3. package/dist/agent/handoff.js.map +1 -1
  4. package/dist/analysis/affected.d.ts +37 -0
  5. package/dist/analysis/affected.js +97 -22
  6. package/dist/analysis/affected.js.map +1 -1
  7. package/dist/analysis/cause.d.ts +32 -0
  8. package/dist/analysis/cause.js +187 -0
  9. package/dist/analysis/cause.js.map +1 -0
  10. package/dist/baseline/approve.d.ts +24 -0
  11. package/dist/baseline/approve.js +54 -0
  12. package/dist/baseline/approve.js.map +1 -0
  13. package/dist/baseline/git-store.d.ts +4 -0
  14. package/dist/baseline/git-store.js +22 -0
  15. package/dist/baseline/git-store.js.map +1 -1
  16. package/dist/browser/acquire.d.ts +11 -0
  17. package/dist/browser/acquire.js +15 -0
  18. package/dist/browser/acquire.js.map +1 -0
  19. package/dist/browser/browser.d.ts +53 -0
  20. package/dist/browser/browser.js +122 -0
  21. package/dist/browser/browser.js.map +1 -0
  22. package/dist/browser/cdp.d.ts +81 -0
  23. package/dist/browser/cdp.js +230 -0
  24. package/dist/browser/cdp.js.map +1 -0
  25. package/dist/browser/index.d.ts +9 -0
  26. package/dist/browser/index.js +10 -0
  27. package/dist/browser/index.js.map +1 -0
  28. package/dist/browser/install.d.ts +33 -0
  29. package/dist/browser/install.js +167 -0
  30. package/dist/browser/install.js.map +1 -0
  31. package/dist/browser/launch.d.ts +37 -0
  32. package/dist/browser/launch.js +265 -0
  33. package/dist/browser/launch.js.map +1 -0
  34. package/dist/browser/page.d.ts +125 -0
  35. package/dist/browser/page.js +564 -0
  36. package/dist/browser/page.js.map +1 -0
  37. package/dist/browser/pins.d.ts +12 -0
  38. package/dist/browser/pins.js +57 -0
  39. package/dist/browser/pins.js.map +1 -0
  40. package/dist/browser/resolve.d.ts +25 -0
  41. package/dist/browser/resolve.js +115 -0
  42. package/dist/browser/resolve.js.map +1 -0
  43. package/dist/browser/selectors.d.ts +10 -0
  44. package/dist/browser/selectors.js +60 -0
  45. package/dist/browser/selectors.js.map +1 -0
  46. package/dist/browser/transport.d.ts +39 -0
  47. package/dist/browser/transport.js +99 -0
  48. package/dist/browser/transport.js.map +1 -0
  49. package/dist/browser/zip.d.ts +27 -0
  50. package/dist/browser/zip.js +241 -0
  51. package/dist/browser/zip.js.map +1 -0
  52. package/dist/capture/capture.d.ts +7 -1
  53. package/dist/capture/capture.js +25 -8
  54. package/dist/capture/capture.js.map +1 -1
  55. package/dist/capture/env.d.ts +1 -1
  56. package/dist/capture/launch.d.ts +19 -1
  57. package/dist/capture/launch.js +91 -1
  58. package/dist/capture/launch.js.map +1 -1
  59. package/dist/capture/pool.d.ts +1 -1
  60. package/dist/capture/pool.js +41 -8
  61. package/dist/capture/pool.js.map +1 -1
  62. package/dist/capture/settle.d.ts +1 -1
  63. package/dist/capture/settle.js +2 -0
  64. package/dist/capture/settle.js.map +1 -1
  65. package/dist/capture/snap.d.ts +43 -0
  66. package/dist/capture/snap.js +103 -0
  67. package/dist/capture/snap.js.map +1 -0
  68. package/dist/capture/structure.d.ts +77 -0
  69. package/dist/capture/structure.js +498 -0
  70. package/dist/capture/structure.js.map +1 -0
  71. package/dist/diff/compare.d.ts +19 -0
  72. package/dist/diff/compare.js +19 -0
  73. package/dist/diff/compare.js.map +1 -0
  74. package/dist/diff/crops.d.ts +26 -0
  75. package/dist/diff/crops.js +92 -0
  76. package/dist/diff/crops.js.map +1 -0
  77. package/dist/diff/structural/classify.d.ts +29 -0
  78. package/dist/diff/structural/classify.js +113 -0
  79. package/dist/diff/structural/classify.js.map +1 -0
  80. package/dist/diff/structural/coverage.d.ts +11 -0
  81. package/dist/diff/structural/coverage.js +37 -0
  82. package/dist/diff/structural/coverage.js.map +1 -0
  83. package/dist/diff/structural/deltas.d.ts +29 -0
  84. package/dist/diff/structural/deltas.js +218 -0
  85. package/dist/diff/structural/deltas.js.map +1 -0
  86. package/dist/diff/structural/disambiguate.d.ts +3 -0
  87. package/dist/diff/structural/disambiguate.js +89 -0
  88. package/dist/diff/structural/disambiguate.js.map +1 -0
  89. package/dist/diff/structural/label.d.ts +15 -0
  90. package/dist/diff/structural/label.js +64 -0
  91. package/dist/diff/structural/label.js.map +1 -0
  92. package/dist/diff/structural/match.d.ts +13 -0
  93. package/dist/diff/structural/match.js +135 -0
  94. package/dist/diff/structural/match.js.map +1 -0
  95. package/dist/diff/structural/shift.d.ts +2 -0
  96. package/dist/diff/structural/shift.js +144 -0
  97. package/dist/diff/structural/shift.js.map +1 -0
  98. package/dist/diff/structural/summary.d.ts +31 -0
  99. package/dist/diff/structural/summary.js +420 -0
  100. package/dist/diff/structural/summary.js.map +1 -0
  101. package/dist/diff/structural.d.ts +40 -0
  102. package/dist/diff/structural.js +219 -0
  103. package/dist/diff/structural.js.map +1 -0
  104. package/dist/index.d.ts +25 -3
  105. package/dist/index.js +29 -2
  106. package/dist/index.js.map +1 -1
  107. package/dist/platform.d.ts +1 -1
  108. package/dist/platforms/urls.d.ts +3 -0
  109. package/dist/platforms/urls.js +89 -0
  110. package/dist/platforms/urls.js.map +1 -0
  111. package/dist/report/comment.js +9 -3
  112. package/dist/report/comment.js.map +1 -1
  113. package/dist/report/format.d.ts +18 -0
  114. package/dist/report/format.js +20 -0
  115. package/dist/report/format.js.map +1 -1
  116. package/dist/report/html.js +2 -2
  117. package/dist/report/html.js.map +1 -1
  118. package/dist/run/groups.d.ts +2 -0
  119. package/dist/run/groups.js +45 -0
  120. package/dist/run/groups.js.map +1 -0
  121. package/dist/run/run.d.ts +6 -2
  122. package/dist/run/run.js +74 -6
  123. package/dist/run/run.js.map +1 -1
  124. package/dist/shell-quote.d.ts +2 -0
  125. package/dist/shell-quote.js +10 -0
  126. package/dist/shell-quote.js.map +1 -0
  127. package/dist/types.d.ts +199 -1
  128. package/dist/url-platform.d.ts +2 -2
  129. package/dist/url-platform.js +2 -2
  130. package/dist/url-platform.js.map +1 -1
  131. package/package.json +5 -10
@@ -0,0 +1,265 @@
1
+ // packages/core/src/browser/launch.ts
2
+ //
3
+ // Spawn Chrome with the pipe on fds 3/4, as Playwright does (coreBundle.js
4
+ // L39607). Measured 74–91 ms to Browser.getVersion on an M-series Mac, the
5
+ // same as Playwright's launch: the cost is Chrome's, not the driver's.
6
+ //
7
+ // `spawn` is injectable so the no-browser probe (scripts/check-diff.mjs) and
8
+ // tests can assert nothing is launched without patching node:child_process.
9
+ import { spawn as nodeSpawn } from 'node:child_process';
10
+ import { rmSync } from 'node:fs';
11
+ import { lstat, mkdir, mkdtemp, readdir, rm } from 'node:fs/promises';
12
+ import { tmpdir } from 'node:os';
13
+ import path from 'node:path';
14
+ import { chromeArgs } from '../capture/launch.js';
15
+ import { CdpConnection } from './cdp.js';
16
+ import { PipeTransport } from './transport.js';
17
+ /** How long Browser.close gets, then how long SIGTERM gets, before SIGKILL. */
18
+ const GRACEFUL_CLOSE_MS = 2000;
19
+ const TERM_GRACE_MS = 1000;
20
+ /** After SIGKILL the exit event is imminent; bound the wait so close() cannot hang. */
21
+ const KILL_WAIT_MS = 2000;
22
+ /** Chrome answers Browser.getVersion in ~80 ms; this only bounds a wedged binary. */
23
+ const HANDSHAKE_TIMEOUT_MS = 30_000;
24
+ /** How long a failed launch waits for the exit event and the last of stderr. */
25
+ const FAILURE_WAIT_MS = 2000;
26
+ const STDERR_DRAIN_MS = 300;
27
+ /** A profile of a dead owner is only swept once it is this old. */
28
+ const STALE_PROFILE_MS = 10 * 60_000;
29
+ /** Live launches, so a signal or exit can take every Chrome and profile with it. */
30
+ const live = new Set();
31
+ let handlersInstalled = false;
32
+ /** Kill every live Chrome and remove its profile, synchronously. Exported for tests. */
33
+ export function terminateAll() {
34
+ for (const l of live) {
35
+ if (!l.gone) {
36
+ try {
37
+ l.proc.kill('SIGKILL');
38
+ }
39
+ catch {
40
+ // already gone
41
+ }
42
+ }
43
+ try {
44
+ rmSync(l.userDataDir, { recursive: true, force: true, maxRetries: 3 });
45
+ }
46
+ catch {
47
+ // best effort: the stale-profile sweep gets it on a later launch
48
+ }
49
+ }
50
+ live.clear();
51
+ }
52
+ const signalHandlers = new Map();
53
+ function installExitHandlers() {
54
+ if (!handlersInstalled) {
55
+ handlersInstalled = true;
56
+ process.on('exit', terminateAll);
57
+ }
58
+ for (const sig of ['SIGINT', 'SIGTERM']) {
59
+ if (signalHandlers.has(sig))
60
+ continue;
61
+ const handler = () => {
62
+ // Detach first: re-raising with our listener attached would loop forever.
63
+ process.removeListener(sig, handler);
64
+ signalHandlers.delete(sig);
65
+ terminateAll();
66
+ // Only when nobody else listens is dying the right response; a host with
67
+ // its own handler (a CLI that prints "interrupted") decides for itself.
68
+ if (process.listenerCount(sig) === 0)
69
+ process.kill(process.pid, sig);
70
+ };
71
+ signalHandlers.set(sig, handler);
72
+ process.on(sig, handler);
73
+ }
74
+ }
75
+ const PROFILE_PREFIX = 'jux-chrome-';
76
+ /**
77
+ * Remove profiles left by a jux that was SIGKILLed or lost power: named
78
+ * `jux-chrome-<pid>-…`, owner pid dead, untouched for 10 minutes. Anything
79
+ * else in the directory is not ours to touch.
80
+ */
81
+ export async function sweepStaleProfiles(dir) {
82
+ try {
83
+ for (const name of await readdir(dir)) {
84
+ const m = /^jux-chrome-(\d+)-/.exec(name);
85
+ if (!m)
86
+ continue;
87
+ try {
88
+ process.kill(Number(m[1]), 0);
89
+ continue; // owner alive (EPERM also lands here via the throw below)
90
+ }
91
+ catch (e) {
92
+ if (e.code !== 'ESRCH')
93
+ continue;
94
+ }
95
+ const full = path.join(dir, name);
96
+ try {
97
+ // lstat: a symlink entry is not a directory of ours, whatever it points at.
98
+ const st = await lstat(full);
99
+ if (!st.isDirectory() || Date.now() - st.mtimeMs < STALE_PROFILE_MS)
100
+ continue;
101
+ await rm(full, { recursive: true, force: true, maxRetries: 3 });
102
+ }
103
+ catch {
104
+ // raced with another sweeper, or unreadable: leave it
105
+ }
106
+ }
107
+ }
108
+ catch {
109
+ // no readable tmpdir: nothing to sweep
110
+ }
111
+ }
112
+ /**
113
+ * The per-user directory every profile lives in. A shared tmpdir lets another
114
+ * user plant `jux-chrome-<dead pid>-x` (or swap one under us) and have our
115
+ * sweep delete through it, so profiles and the sweep stay inside a directory
116
+ * only we can write. Verified with lstat, never chmod/chown'd: a dir that is
117
+ * not ours is refused, not repaired. Windows has no uid; its tmpdir is already
118
+ * per-user.
119
+ */
120
+ export async function privateProfileRoot(opts = {}) {
121
+ const uid = 'uid' in opts ? opts.uid : process.getuid?.();
122
+ const root = path.join(opts.base ?? tmpdir(), `jux-${uid ?? 'u'}`);
123
+ const refuse = (why) => new Error(`jux: refusing to use ${root}: ${why}. Remove it (rm -rf ${root}) and run jux again.`);
124
+ await mkdir(root, { mode: 0o700 }).catch((e) => {
125
+ if (e.code !== 'EEXIST')
126
+ throw e;
127
+ });
128
+ const st = await lstat(root);
129
+ if (st.isSymbolicLink() || !st.isDirectory())
130
+ throw refuse('it is not a real directory');
131
+ if (uid !== undefined) {
132
+ if (st.uid !== uid)
133
+ throw refuse('it is owned by another user');
134
+ if ((st.mode & 0o022) !== 0)
135
+ throw refuse('it is writable by other users');
136
+ }
137
+ return root;
138
+ }
139
+ async function createProfileDir() {
140
+ const root = await privateProfileRoot();
141
+ await sweepStaleProfiles(root);
142
+ return mkdtemp(path.join(root, `${PROFILE_PREFIX}${process.pid}-`));
143
+ }
144
+ export async function launchChrome(opts) {
145
+ const spawn = opts.spawn ?? nodeSpawn;
146
+ const userDataDir = await createProfileDir();
147
+ const args = chromeArgs({ userDataDir, args: opts.args, headless: opts.headless });
148
+ let proc;
149
+ try {
150
+ proc = spawn(opts.executablePath, args, {
151
+ // stdin/stdout ignored, stderr kept for the "missing shared library"
152
+ // message on Linux, 3 = Chrome reads, 4 = Chrome writes.
153
+ stdio: ['ignore', 'ignore', 'pipe', 'pipe', 'pipe'],
154
+ });
155
+ }
156
+ catch (error) {
157
+ await rm(userDataDir, { recursive: true, force: true });
158
+ throw new Error(`jux: could not launch the browser: ${describeSpawnError(error, opts.executablePath)}`, { cause: error });
159
+ }
160
+ const entry = { proc, userDataDir, gone: false };
161
+ live.add(entry);
162
+ installExitHandlers();
163
+ let stderr = '';
164
+ proc.stderr?.on('data', (d) => {
165
+ if (stderr.length < 8192)
166
+ stderr += d.toString();
167
+ });
168
+ // One promise for "the process is gone", resolved never rejected, so an
169
+ // exit after a successful launch is not an unhandled rejection.
170
+ const exited = new Promise((resolve) => {
171
+ proc.on('error', (error) => resolve({ code: null, error }));
172
+ proc.once('exit', (code) => resolve({ code }));
173
+ });
174
+ void exited.then(() => {
175
+ entry.gone = true;
176
+ live.delete(entry);
177
+ });
178
+ const transport = new PipeTransport(proc.stdio[3], proc.stdio[4]);
179
+ const connection = new CdpConnection(transport);
180
+ void exited.then(() => transport.close());
181
+ let stderrClosed = !proc.stderr;
182
+ proc.stderr?.once('close', () => (stderrClosed = true));
183
+ // Race the handshake against an early exit (bad binary, missing .so) and a
184
+ // wedged binary. Any failure ends in one place that kills, waits, cleans up
185
+ // and explains.
186
+ const timeoutMs = opts.handshakeTimeoutMs ?? HANDSHAKE_TIMEOUT_MS;
187
+ let timer;
188
+ const outcome = await Promise.race([
189
+ connection.send('Browser.getVersion').then(() => 'ready', () => 'closed'),
190
+ exited.then(() => 'closed'),
191
+ new Promise((r) => (timer = setTimeout(() => r('timeout'), timeoutMs))),
192
+ ]);
193
+ clearTimeout(timer);
194
+ if (outcome !== 'ready') {
195
+ if (outcome === 'timeout' && !entry.gone)
196
+ proc.kill('SIGKILL');
197
+ // Ref'd timers here: an async spawn failure (EACCES on the 'error' event)
198
+ // leaves no child handle and a stderr that never closes, so with unref'd
199
+ // timers a bare `jux snap --chrome <non-exec>` drained its event loop here
200
+ // and exited 0 silently, leaking the profile.
201
+ const result = await Promise.race([exited, sleep(FAILURE_WAIT_MS, { ref: true })]);
202
+ if (!entry.gone)
203
+ proc.kill('SIGKILL');
204
+ if (!stderrClosed)
205
+ await sleep(STDERR_DRAIN_MS, { ref: true });
206
+ connection.close();
207
+ live.delete(entry);
208
+ await rm(userDataDir, { recursive: true, force: true, maxRetries: 3 });
209
+ const exe = opts.executablePath;
210
+ const why = outcome === 'timeout'
211
+ ? `the browser at ${exe} did not answer within ${timeoutMs} ms and was killed. Reinstall it with \`npx -p @juxtapose/cli jux browser install\`, or point JUX_CHROME at a working Chrome.`
212
+ : result?.error
213
+ ? describeSpawnError(result.error, exe)
214
+ : `the browser at ${exe} exited with code ${result?.code ?? 'unknown'} before it was ready.${describeStderr(stderr)}`;
215
+ throw new Error(`jux: could not launch the browser: ${why}`);
216
+ }
217
+ let closing = null;
218
+ const close = () => (closing ??= (async () => {
219
+ if (!connection.closed) {
220
+ connection.send('Browser.close').catch(() => { });
221
+ await Promise.race([exited, sleep(GRACEFUL_CLOSE_MS)]);
222
+ }
223
+ // Escalate, then wait for the exit so no zombie outlives close().
224
+ if (!entry.gone) {
225
+ proc.kill('SIGTERM');
226
+ await Promise.race([exited, sleep(TERM_GRACE_MS)]);
227
+ }
228
+ if (!entry.gone) {
229
+ proc.kill('SIGKILL');
230
+ await Promise.race([exited, sleep(KILL_WAIT_MS)]);
231
+ }
232
+ connection.close();
233
+ live.delete(entry);
234
+ await rm(userDataDir, { recursive: true, force: true });
235
+ })());
236
+ return { connection, pid: proc.pid, userDataDir, close };
237
+ }
238
+ /**
239
+ * Unref'd by default: close() waits on a live child, whose handle already holds
240
+ * the loop, and must not keep a host alive on its own. Pass `ref` where nothing
241
+ * else may be holding the loop open.
242
+ */
243
+ const sleep = (ms, opts = {}) => new Promise((r) => {
244
+ const t = setTimeout(r, ms);
245
+ if (!opts.ref)
246
+ t.unref();
247
+ });
248
+ /** ENOENT / EACCES on spawn: say what to do, not just what the kernel said. */
249
+ function describeSpawnError(error, executablePath) {
250
+ const code = error.code;
251
+ if (code === 'ENOENT' || code === 'EACCES') {
252
+ const what = code === 'ENOENT' ? 'does not exist' : 'is not executable';
253
+ return `${executablePath} ${what}. Install the pinned browser with \`npx -p @juxtapose/cli jux browser install\`, or point JUX_CHROME at a Chrome you already have.`;
254
+ }
255
+ return `${error.message} (${executablePath})`;
256
+ }
257
+ /** Linux: `error while loading shared libraries: libnss3.so` → name the apt line. */
258
+ function describeStderr(stderr) {
259
+ const m = /error while loading shared libraries: ([^:]+):/.exec(stderr);
260
+ if (m) {
261
+ return ` Missing system library ${m[1]}. On Ubuntu 24.04: sudo apt-get install libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libatspi2.0-0t64 libcairo2 libcups2t64 libdbus-1-3 libdrm2 libgbm1 libglib2.0-0t64 libnspr4 libnss3 libpango-1.0-0 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxkbcommon0 libxrandr2`;
262
+ }
263
+ return stderr.trim() ? `\n${stderr.trim().split('\n').slice(-3).join('\n')}` : '';
264
+ }
265
+ //# sourceMappingURL=launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ import type { Viewport } from '../types.js';
2
+ import { CdpConnection } from './cdp.js';
3
+ export declare class TimeoutError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ /** The renderer died (OOM, Page.crash, a GPU fault); the page cannot be used again. */
7
+ export declare class PageCrashedError extends Error {
8
+ constructor();
9
+ }
10
+ /**
11
+ * The page a platform adapter drives: the public adapter API, exported from
12
+ * `@juxtapose/core`. Adapters receive it in `showStory`, `settle`,
13
+ * `switchStory` and `readLiveParams`.
14
+ *
15
+ * Stable (semver): `goto`, `url`, `evaluate`, `waitForFunction`,
16
+ * `waitForSelector`, `addStyleTag`, `setViewportSize`, `screenshot`.
17
+ * Everything else serves core's own pipeline (snap, structure, the pool) and
18
+ * may change without a major version.
19
+ *
20
+ * Selectors (`waitForSelector`, `screenshot({ mask })`) are CSS, resolved
21
+ * through open shadow roots; anything else throws synchronously.
22
+ */
23
+ export interface Page {
24
+ /** Navigate and resolve on the main frame's `load`; rejects at `timeout` with the URL. */
25
+ goto(url: string, opts?: {
26
+ timeout?: number;
27
+ }): Promise<void>;
28
+ url(): string;
29
+ evaluate<R, A = undefined>(fn: string | ((arg: A) => R | Promise<R>), arg?: A, opts?: {
30
+ timeout?: number;
31
+ }): Promise<R>;
32
+ waitForFunction<A = undefined>(fn: (arg: A) => unknown, arg?: A, opts?: {
33
+ timeout?: number;
34
+ }): Promise<void>;
35
+ waitForSelector(selector: string, opts?: {
36
+ timeout?: number;
37
+ }): Promise<void>;
38
+ addStyleTag(opts: {
39
+ content: string;
40
+ }): Promise<void>;
41
+ setViewportSize(viewport: Viewport): Promise<void>;
42
+ screenshot(opts?: {
43
+ mask?: string[];
44
+ }): Promise<Buffer>;
45
+ /**
46
+ * Raw CDP on this page's session, for DOMSnapshot.
47
+ * @internal Not part of the adapter API; the protocol surface is Chrome's, not ours.
48
+ */
49
+ send<T = unknown>(method: string, params?: object): Promise<T>;
50
+ /** HTTP status of each main-document response; returns the unsubscribe. */
51
+ onMainResponse(handler: (status: number) => void): () => void;
52
+ /** Storage.clearDataForOrigin on this page's session: localStorage, IndexedDB, Cache Storage, service workers. */
53
+ clearOrigin(origin: string): Promise<void>;
54
+ close(): Promise<void>;
55
+ }
56
+ export declare class CdpPage implements Page {
57
+ private readonly connection;
58
+ readonly targetId: string;
59
+ readonly sessionId: string;
60
+ private currentUrl;
61
+ private viewport;
62
+ private closed;
63
+ /**
64
+ * Why the page is unusable, once it is. `goneP` rejects with it at that
65
+ * moment and every send, evaluate and goto races it, so work already in
66
+ * flight fails at once: Chrome never answers a command on a crashed or
67
+ * detached session, and a committed navigation whose `load` never comes
68
+ * would otherwise hold a pool worker for its full timeout.
69
+ */
70
+ private goneError;
71
+ private rejectGone;
72
+ private readonly goneP;
73
+ /** Every connection listener this page holds; dispose() removes them all. */
74
+ private readonly offs;
75
+ private constructor();
76
+ /** The spike's init list (spec §Decisions 3), plus Log.enable which Playwright also sends. */
77
+ static create(connection: CdpConnection, targetId: string, sessionId: string, opts: {
78
+ viewport: Viewport;
79
+ blockServiceWorkers: boolean;
80
+ os: NodeJS.Platform;
81
+ }): Promise<CdpPage>;
82
+ send<T = unknown>(method: string, params?: object): Promise<T>;
83
+ url(): string;
84
+ onMainResponse(handler: (status: number) => void): () => void;
85
+ /**
86
+ * Page.navigate, then the main frame's `load` for the document that
87
+ * navigation created. The timeout covers the whole thing: Chrome answers
88
+ * Page.navigate only at commit or failure, so a server that never responds
89
+ * never replies. A child frame's own `load` must not count (a same-process
90
+ * iframe fires one for itself), nor may a late `load` from the previous
91
+ * document: Playwright waits on the new document's loaderId.
92
+ */
93
+ goto(url: string, opts?: {
94
+ timeout?: number;
95
+ }): Promise<void>;
96
+ evaluate<R, A = undefined>(fn: string | ((arg: A) => R | Promise<R>), arg?: A, opts?: {
97
+ timeout?: number;
98
+ }): Promise<R>;
99
+ /** Playwright polls on requestAnimationFrame by default (polling: 'raf'). */
100
+ waitForFunction<A = undefined>(fn: (arg: A) => unknown, arg?: A, opts?: {
101
+ timeout?: number;
102
+ }): Promise<void>;
103
+ waitForSelector(selector: string, opts?: {
104
+ timeout?: number;
105
+ }): Promise<void>;
106
+ /** rAF-poll `predicate(arg)` in the page; true once truthy, false at the in-page cap. */
107
+ private poll;
108
+ /** Frame._addStyleTag → addStyleContent, verbatim. */
109
+ addStyleTag(opts: {
110
+ content: string;
111
+ }): Promise<void>;
112
+ setViewportSize(viewport: Viewport): Promise<void>;
113
+ /** Screenshotter.screenshotPage: prepare → fonts.ready → mask → getLayoutMetrics → captureScreenshot → cleanup. */
114
+ screenshot(opts?: {
115
+ mask?: string[];
116
+ }): Promise<Buffer>;
117
+ clearOrigin(origin: string): Promise<void>;
118
+ close(): Promise<void>;
119
+ /** Mark closed and drop every listener; idempotent. BrowserContext.close calls it for its pages. */
120
+ dispose(): void;
121
+ /** First cause wins: a crash followed by the context closing still reports the crash. */
122
+ private fail;
123
+ /** `p`, unless the page goes first. */
124
+ private guard;
125
+ }