@mochi.js/core 0.6.0 → 0.8.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 +2 -2
- package/package.json +3 -4
- package/src/__tests__/cookies-jar.test.ts +2 -3
- package/src/__tests__/default-profile.test.ts +6 -8
- package/src/__tests__/dx-cluster.e2e.test.ts +1 -2
- package/src/__tests__/geo-consistency.test.ts +0 -1
- package/src/__tests__/geo-probe.test.ts +13 -13
- package/src/__tests__/init-injector.e2e.test.ts +0 -1
- package/src/__tests__/init-injector.test.ts +1 -2
- package/src/__tests__/inject.test.ts +1 -2
- package/src/__tests__/page-dx-cluster.test.ts +3 -4
- package/src/__tests__/piercing.test.ts +1 -1
- package/src/__tests__/proc-linux-server.test.ts +4 -4
- package/src/__tests__/proc.test.ts +3 -3
- package/src/__tests__/proxy-auth.test.ts +1 -2
- package/src/__tests__/screenshot.e2e.test.ts +1 -1
- package/src/__tests__/screenshot.test.ts +1 -1
- package/src/__tests__/window-size.e2e.test.ts +0 -1
- package/src/cdp/types.ts +0 -1
- package/src/default-profile.ts +6 -8
- package/src/geo-consistency.ts +0 -1
- package/src/geo-probe.ts +37 -32
- package/src/index.ts +1 -1
- package/src/launch.ts +38 -52
- package/src/page/element-handle.ts +0 -1
- package/src/page/piercing.ts +0 -1
- package/src/page/selector.ts +0 -1
- package/src/page.ts +31 -14
- package/src/proc.ts +5 -6
- package/src/proxy-auth.ts +1 -3
- package/src/session.ts +489 -124
- package/src/version.ts +1 -1
package/src/launch.ts
CHANGED
|
@@ -92,7 +92,7 @@ export interface LaunchOptions {
|
|
|
92
92
|
* string (looked up against `KNOWN_PROFILE_IDS`) or an inline `ProfileV1`
|
|
93
93
|
* object.
|
|
94
94
|
*
|
|
95
|
-
* **Optional
|
|
95
|
+
* **Optional** — when omitted, mochi auto-picks the
|
|
96
96
|
* profile whose declared OS matches the host's `process.platform` /
|
|
97
97
|
* `process.arch` pair via {@link defaultProfileForHost}:
|
|
98
98
|
*
|
|
@@ -120,7 +120,7 @@ export interface LaunchOptions {
|
|
|
120
120
|
* `false` (default in v0.1) runs headful. New code should prefer
|
|
121
121
|
* {@link headlessMode}, which is more expressive AND env-aware.
|
|
122
122
|
*
|
|
123
|
-
* Resolution priority
|
|
123
|
+
* Resolution priority:
|
|
124
124
|
*
|
|
125
125
|
* 1. `headlessMode` if set.
|
|
126
126
|
* 2. Else `headless: true → "new"`, `headless: false → "off"`.
|
|
@@ -130,7 +130,7 @@ export interface LaunchOptions {
|
|
|
130
130
|
*/
|
|
131
131
|
headless?: boolean;
|
|
132
132
|
/**
|
|
133
|
-
* Headless dispatch mode
|
|
133
|
+
* Headless dispatch mode. One of:
|
|
134
134
|
*
|
|
135
135
|
* - `"new"` — modern Chromium headless (`--headless=new`). Full
|
|
136
136
|
* rendering, near-byte-identical to headful for
|
|
@@ -178,7 +178,7 @@ export interface LaunchOptions {
|
|
|
178
178
|
* trivially fingerprinted as Chromium-for-Testing.
|
|
179
179
|
*
|
|
180
180
|
* Defaults to `false`. PLAN.md §12.1 (capture must run against bare
|
|
181
|
-
* Chromium);
|
|
181
|
+
* Chromium);
|
|
182
182
|
*/
|
|
183
183
|
bypassInject?: boolean;
|
|
184
184
|
/**
|
|
@@ -199,7 +199,7 @@ export interface LaunchOptions {
|
|
|
199
199
|
*
|
|
200
200
|
* Pairs with — but is independent of — {@link bypassInject}. Capture
|
|
201
201
|
* flows set both `true`; harness conformance runs set `hermetic: true`
|
|
202
|
-
* with full inject pipeline active. PLAN.md §8.6 +
|
|
202
|
+
* with full inject pipeline active. PLAN.md §8.6 +
|
|
203
203
|
*/
|
|
204
204
|
hermetic?: boolean;
|
|
205
205
|
/**
|
|
@@ -235,13 +235,13 @@ export interface LaunchOptions {
|
|
|
235
235
|
* - `"off"` — skip the probe entirely. Use in offline tests / when
|
|
236
236
|
* the probe service is rate-limited.
|
|
237
237
|
*
|
|
238
|
-
* The probe is a single GET through
|
|
239
|
-
* `
|
|
240
|
-
* traffic
|
|
241
|
-
* cached across sessions — proxy IPs
|
|
238
|
+
* The probe is a single GET through Chromium itself (Session.fetch via
|
|
239
|
+
* CDP `Network.loadNetworkResource`), so the geo service sees the same
|
|
240
|
+
* JA4 / headers as user traffic by definition. 4-attempt cap, 2s per
|
|
241
|
+
* endpoint. Probe results are NOT cached across sessions — proxy IPs
|
|
242
|
+
* rotate.
|
|
242
243
|
*
|
|
243
244
|
* @see PLAN.md §9 (relational consistency, IP/TZ/Locale axis)
|
|
244
|
-
* @see tasks/0262-ip-tz-locale-exit-consistency.md
|
|
245
245
|
*/
|
|
246
246
|
geoConsistency?: GeoConsistencyMode;
|
|
247
247
|
}
|
|
@@ -255,8 +255,8 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
255
255
|
const normalized = normalizeProxy(opts.proxy);
|
|
256
256
|
|
|
257
257
|
// Resolve the `MatrixV1` BEFORE spawning so matrix-derived values flow
|
|
258
|
-
// into both the `--lang` flag
|
|
259
|
-
|
|
258
|
+
// into both the `--lang` flag and `--window-size` flag
|
|
259
|
+
//. The matrix is otherwise read post-spawn for inject;
|
|
260
260
|
// deriving early is cheap (~µs, pure function) and lets us close the
|
|
261
261
|
// I-5 leaks between Chromium's native network/OS-window state and the
|
|
262
262
|
// JS-layer spoof.
|
|
@@ -275,7 +275,7 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
275
275
|
if (profileSource.autoPicked) {
|
|
276
276
|
// One info-level log line so users can see what mochi inferred without
|
|
277
277
|
// calling `defaultProfileForHost()` themselves. Wording is pinned by
|
|
278
|
-
//
|
|
278
|
+
// — keep stable so docs + LLM-context blocks stay correct.
|
|
279
279
|
// (Routed through `console.warn` to match the existing diagnostic
|
|
280
280
|
// channel for `geoConsistency` / Linux-server inference; `console.info`
|
|
281
281
|
// is gated by the workspace lint config — `noConsole` only allows
|
|
@@ -289,9 +289,10 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
289
289
|
|
|
290
290
|
// Task 0262 — exit-IP / TZ / locale reconciliation.
|
|
291
291
|
//
|
|
292
|
-
// Probe the apparent exit IP through the configured proxy
|
|
293
|
-
//
|
|
294
|
-
//
|
|
292
|
+
// Probe the apparent exit IP through the configured proxy. Post-0.7
|
|
293
|
+
// the probe runs through Chromium itself (Session.fetch via CDP
|
|
294
|
+
// `Network.loadNetworkResource`), so the geo service sees the same
|
|
295
|
+
// JA4 / headers as user traffic by definition. Cross-reference against
|
|
295
296
|
// `(matrix.timezone, matrix.locale)` and apply `geoConsistency`. The
|
|
296
297
|
// adjusted matrix flows into BOTH `spawnChromium` (so `--lang` reflects
|
|
297
298
|
// any override) AND `Session` (so inject + the CDP `Emulation.set
|
|
@@ -303,7 +304,7 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
303
304
|
let adjustedMatrix = matrix;
|
|
304
305
|
if (geoMode !== "off") {
|
|
305
306
|
const geo = await probeExitGeo({
|
|
306
|
-
...(normalized?.
|
|
307
|
+
...(normalized?.proxy !== undefined ? { proxy: normalized.proxy } : {}),
|
|
307
308
|
matrix,
|
|
308
309
|
});
|
|
309
310
|
// Strict mode throws GeoMismatchError on real mismatch; let it
|
|
@@ -359,13 +360,13 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
359
360
|
// multi-locale list still flows through `matrix.languages` to the
|
|
360
361
|
// inject layer's `navigator.languages` spoof; Chromium derives the
|
|
361
362
|
// q-weighted `Accept-Language` value from the single `--lang` primary
|
|
362
|
-
// automatically.
|
|
363
|
+
// automatically.
|
|
363
364
|
locale: adjustedMatrix.locale,
|
|
364
365
|
// Pin OS-level outer window from the matrix's display geometry so
|
|
365
366
|
// `window.outerWidth/outerHeight` (which reads from the OS window,
|
|
366
367
|
// NOT the JS-spoofed `screen.*`) matches the spoof. Closes the
|
|
367
368
|
// `fingerprint-scan.com` 800×600 leak under `--headless=new`.
|
|
368
|
-
// UDC fixes the same issue at `__init__.py:410-411`.
|
|
369
|
+
// UDC fixes the same issue at `__init__.py:410-411`.
|
|
369
370
|
//
|
|
370
371
|
// (`adjustedMatrix.display` === `matrix.display` since geo reconcile
|
|
371
372
|
// only touches timezone/locale/languages — but we use the adjusted
|
|
@@ -395,10 +396,11 @@ export async function launch(opts: LaunchOptions): Promise<Session> {
|
|
|
395
396
|
seed: opts.seed,
|
|
396
397
|
...(opts.timeout !== undefined ? { defaultTimeoutMs: opts.timeout } : {}),
|
|
397
398
|
...(opts.bypassInject === true ? { bypassInject: true } : {}),
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
|
|
399
|
+
// Proxy auth is the only piece that needs explicit Session-side
|
|
400
|
+
// wiring (the `--proxy-server` flag is already on Chromium's command
|
|
401
|
+
// line above). Out-of-band `Session.fetch` traffic rides Chromium's
|
|
402
|
+
// network stack post-0.7, so it inherits the `--proxy-server` egress
|
|
403
|
+
// automatically — no per-call proxy URL needed.
|
|
402
404
|
...(normalized?.auth !== undefined ? { proxyAuth: normalized.auth } : {}),
|
|
403
405
|
...(opts.challenges !== undefined ? { challenges: opts.challenges } : {}),
|
|
404
406
|
});
|
|
@@ -417,16 +419,15 @@ export const mochi = {
|
|
|
417
419
|
* Inspect what mochi would infer about the current process environment for
|
|
418
420
|
* Linux-server detection (drives `headlessMode` defaulting). Pure read of
|
|
419
421
|
* `process.platform`, `process.env.DISPLAY`, `process.env.WAYLAND_DISPLAY`,
|
|
420
|
-
* `process.getuid?.()`, and the container probe paths.
|
|
422
|
+
* `process.getuid?.()`, and the container probe paths.
|
|
421
423
|
*/
|
|
422
424
|
detectLinuxServerEnv: probeLinuxServerEnv,
|
|
423
425
|
/**
|
|
424
426
|
* Inspect which profile id `mochi.launch` would auto-pick on the current
|
|
425
427
|
* host when `profile` is omitted. Pure read of `process.platform` /
|
|
426
428
|
* `process.arch`. Returns `null` on unsupported hosts — the launcher
|
|
427
|
-
* throws on that path with a list of explicit profile IDs.
|
|
429
|
+
* throws on that path with a list of explicit profile IDs.
|
|
428
430
|
*
|
|
429
|
-
* @see tasks/0271-the-linux-os-thesis.md — the strategic thesis
|
|
430
431
|
* @see https://mochijs.com/docs/concepts/stealth-philosophy
|
|
431
432
|
*/
|
|
432
433
|
defaultProfileForHost,
|
|
@@ -463,9 +464,10 @@ export function resolveHeadlessMode(
|
|
|
463
464
|
* Reconcile the two `LaunchOptions.proxy` shapes (URL string and
|
|
464
465
|
* `ProxyConfig` record) into a single normalized record carrying:
|
|
465
466
|
* - `server`: auth-stripped URL safe to feed `--proxy-server=`.
|
|
466
|
-
* - `
|
|
467
|
-
*
|
|
468
|
-
*
|
|
467
|
+
* - `proxy`: the auth-stripped URL forwarded to the geo-probe so it
|
|
468
|
+
* can record the egress on diagnostics. (Kept for API parity even
|
|
469
|
+
* though the probe now rides Session.fetch + Chromium's network
|
|
470
|
+
* stack — i.e. picks up `--proxy-server` automatically.)
|
|
469
471
|
* - `auth`: parsed credentials for the CDP auth handler. Undefined when
|
|
470
472
|
* no creds were supplied.
|
|
471
473
|
*
|
|
@@ -474,7 +476,7 @@ export function resolveHeadlessMode(
|
|
|
474
476
|
function normalizeProxy(p: LaunchOptions["proxy"]):
|
|
475
477
|
| {
|
|
476
478
|
server: string;
|
|
477
|
-
|
|
479
|
+
proxy: string;
|
|
478
480
|
auth?: { username: string; password: string };
|
|
479
481
|
}
|
|
480
482
|
| undefined {
|
|
@@ -484,7 +486,7 @@ function normalizeProxy(p: LaunchOptions["proxy"]):
|
|
|
484
486
|
const parsed = parseProxyUrl(p);
|
|
485
487
|
return {
|
|
486
488
|
server: parsed.server,
|
|
487
|
-
|
|
489
|
+
proxy: parsed.server,
|
|
488
490
|
...(parsed.auth !== undefined ? { auth: parsed.auth } : {}),
|
|
489
491
|
};
|
|
490
492
|
}
|
|
@@ -493,31 +495,13 @@ function normalizeProxy(p: LaunchOptions["proxy"]):
|
|
|
493
495
|
const parsed = parseProxyUrl(p.server);
|
|
494
496
|
const auth =
|
|
495
497
|
p.username !== undefined ? { username: p.username, password: p.password ?? "" } : parsed.auth;
|
|
496
|
-
// Reconstruct the netProxy URL preserving any explicit auth (wreq path).
|
|
497
|
-
const netProxy = auth !== undefined ? injectAuth(parsed.server, auth) : parsed.server;
|
|
498
498
|
return {
|
|
499
499
|
server: parsed.server,
|
|
500
|
-
|
|
500
|
+
proxy: parsed.server,
|
|
501
501
|
...(auth !== undefined ? { auth } : {}),
|
|
502
502
|
};
|
|
503
503
|
}
|
|
504
504
|
|
|
505
|
-
/**
|
|
506
|
-
* Inject `username:password@` into a server URL, percent-encoding both
|
|
507
|
-
* components so reserved characters round-trip cleanly through wreq's URL
|
|
508
|
-
* parser.
|
|
509
|
-
*/
|
|
510
|
-
function injectAuth(server: string, auth: { username: string; password: string }): string {
|
|
511
|
-
const u = encodeURIComponent(auth.username);
|
|
512
|
-
const p = encodeURIComponent(auth.password);
|
|
513
|
-
// server is `<protocol>://<host>:<port>` (per parseProxyUrl).
|
|
514
|
-
const idx = server.indexOf("://");
|
|
515
|
-
if (idx < 0) return server;
|
|
516
|
-
const head = server.slice(0, idx + 3);
|
|
517
|
-
const tail = server.slice(idx + 3);
|
|
518
|
-
return `${head}${u}:${p}@${tail}`;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
505
|
/**
|
|
522
506
|
* Resolve `LaunchOptions.profile` into a concrete `ProfileV1` plus the
|
|
523
507
|
* meta-flag the launcher needs to decide whether to log the auto-pick
|
|
@@ -550,7 +534,7 @@ function resolveProfileSource(profile: ProfileId | ProfileV1 | undefined): {
|
|
|
550
534
|
autoPicked: false,
|
|
551
535
|
};
|
|
552
536
|
}
|
|
553
|
-
// Auto-pick branch —
|
|
537
|
+
// Auto-pick branch —
|
|
554
538
|
const picked = defaultProfileForHost();
|
|
555
539
|
if (picked === null) {
|
|
556
540
|
throw new Error(unsupportedHostMessage(process.platform, process.arch));
|
|
@@ -598,7 +582,9 @@ function synthesizePlaceholderProfile(profile: ProfileId): ProfileV1 {
|
|
|
598
582
|
locale: "en-US",
|
|
599
583
|
languages: ["en-US", "en"],
|
|
600
584
|
behavior: { hand: "right", tremor: 0.18, wpm: 60, scrollStyle: "smooth" },
|
|
601
|
-
|
|
585
|
+
// Deprecated — kept for one release for migration; runtime no longer
|
|
586
|
+
// reads the field. Drops in 0.8.
|
|
587
|
+
wreqPreset: "chrome_148_linux",
|
|
602
588
|
userAgent:
|
|
603
589
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
|
604
590
|
uaCh: {},
|
package/src/page/piercing.ts
CHANGED
package/src/page/selector.ts
CHANGED
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
* Throws `SelectorParseError` on syntactically invalid input. The matcher
|
|
32
32
|
* itself never throws — unsupported nodes just don't match.
|
|
33
33
|
*
|
|
34
|
-
* @see tasks/0253-closed-shadow-piercing-locator.md
|
|
35
34
|
* @see PLAN.md §8.2 (forbidden CDP — neither `DOM.getDocument` nor
|
|
36
35
|
* `DOM.resolveNode` is forbidden; both fine).
|
|
37
36
|
*/
|
package/src/page.ts
CHANGED
|
@@ -202,7 +202,7 @@ export interface ScreenshotOptions {
|
|
|
202
202
|
encoding?: "binary" | "base64";
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
// ---- DX cluster: DOM storage + permissions
|
|
205
|
+
// ---- DX cluster: DOM storage + permissions ---------------------
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* Options for {@link Page.localStorage} / {@link Page.sessionStorage}
|
|
@@ -252,43 +252,61 @@ export interface DomStorage {
|
|
|
252
252
|
/**
|
|
253
253
|
* Every browser-level permission descriptor `Browser.grantPermissions` accepts.
|
|
254
254
|
*
|
|
255
|
-
* Pinned to the CDP `Browser.PermissionType` enum on Chromium
|
|
256
|
-
*
|
|
257
|
-
* The list is verbose-on-purpose: we want a contract test
|
|
258
|
-
* Chromium adds a new permission so we can decide
|
|
255
|
+
* Pinned to the CDP `Browser.PermissionType` enum on Chromium 148 (the
|
|
256
|
+
* post-0.7 profile floor — verified `2026-05-09` against the live CDP
|
|
257
|
+
* reference). The list is verbose-on-purpose: we want a contract test
|
|
258
|
+
* to catch the day Chromium adds a new permission so we can decide
|
|
259
|
+
* whether to forward it.
|
|
260
|
+
*
|
|
261
|
+
* Drift history:
|
|
262
|
+
* - 0.7: removed `accessibilityEvents`, `captureHandle`, `flash`,
|
|
263
|
+
* `videoCapturePanTiltZoom` (gone or renamed in 148). Added the XR
|
|
264
|
+
* cluster (`ar`, `vr`, `handTracking`), `automaticFullscreen`,
|
|
265
|
+
* `cameraPanTiltZoom`, `capturedSurfaceControl`, `keyboardLock`,
|
|
266
|
+
* `pointerLock`, `localNetwork`, `localNetworkAccess`,
|
|
267
|
+
* `loopbackNetwork`, `smartCard`, `webPrinting`.
|
|
259
268
|
*
|
|
260
269
|
* @see https://chromedevtools.github.io/devtools-protocol/tot/Browser/#type-PermissionType
|
|
261
270
|
*/
|
|
262
271
|
export const ALL_BROWSER_PERMISSIONS = [
|
|
263
|
-
"
|
|
272
|
+
"ar",
|
|
264
273
|
"audioCapture",
|
|
265
|
-
"
|
|
274
|
+
"automaticFullscreen",
|
|
266
275
|
"backgroundFetch",
|
|
267
|
-
"
|
|
276
|
+
"backgroundSync",
|
|
277
|
+
"cameraPanTiltZoom",
|
|
278
|
+
"capturedSurfaceControl",
|
|
268
279
|
"clipboardReadWrite",
|
|
269
280
|
"clipboardSanitizedWrite",
|
|
270
281
|
"displayCapture",
|
|
271
282
|
"durableStorage",
|
|
272
|
-
"flash",
|
|
273
283
|
"geolocation",
|
|
284
|
+
"handTracking",
|
|
274
285
|
"idleDetection",
|
|
286
|
+
"keyboardLock",
|
|
275
287
|
"localFonts",
|
|
288
|
+
"localNetwork",
|
|
289
|
+
"localNetworkAccess",
|
|
290
|
+
"loopbackNetwork",
|
|
276
291
|
"midi",
|
|
277
292
|
"midiSysex",
|
|
278
293
|
"nfc",
|
|
279
294
|
"notifications",
|
|
280
295
|
"paymentHandler",
|
|
281
296
|
"periodicBackgroundSync",
|
|
297
|
+
"pointerLock",
|
|
282
298
|
"protectedMediaIdentifier",
|
|
283
299
|
"sensors",
|
|
284
|
-
"
|
|
300
|
+
"smartCard",
|
|
285
301
|
"speakerSelection",
|
|
302
|
+
"storageAccess",
|
|
286
303
|
"topLevelStorageAccess",
|
|
287
304
|
"videoCapture",
|
|
288
|
-
"
|
|
305
|
+
"vr",
|
|
289
306
|
"wakeLockScreen",
|
|
290
307
|
"wakeLockSystem",
|
|
291
308
|
"webAppInstallation",
|
|
309
|
+
"webPrinting",
|
|
292
310
|
"windowManagement",
|
|
293
311
|
] as const;
|
|
294
312
|
|
|
@@ -1030,13 +1048,12 @@ export class Page {
|
|
|
1030
1048
|
* Supported selectors (see `selector.ts`): tag / id / class / attribute /
|
|
1031
1049
|
* descendant combinator / comma-separated lists. **Not** supported:
|
|
1032
1050
|
* `>`/`+`/`~` combinators, `:pseudo-classes`, `::pseudo-elements`, XPath.
|
|
1033
|
-
* XPath is a stretch goal
|
|
1051
|
+
* XPath is a stretch goal — TODO if a future surface
|
|
1034
1052
|
* needs it (Turnstile detection only needs CSS).
|
|
1035
1053
|
*
|
|
1036
1054
|
* Performance: O(N) in DOM size per call. Acceptable for v0.2; a per-page
|
|
1037
1055
|
* cache layer is a v0.3+ concern (also called out in 0253).
|
|
1038
1056
|
*
|
|
1039
|
-
* @see tasks/0253-closed-shadow-piercing-locator.md
|
|
1040
1057
|
* @see PLAN.md §8.2 (`DOM.getDocument` and `DOM.resolveNode` are not on the
|
|
1041
1058
|
* forbidden list — both fine to use here).
|
|
1042
1059
|
*/
|
|
@@ -1480,7 +1497,7 @@ function hash01(s: string): number {
|
|
|
1480
1497
|
return (h >>> 0) / 0x1_0000_0000;
|
|
1481
1498
|
}
|
|
1482
1499
|
|
|
1483
|
-
// ---- DOM storage factory
|
|
1500
|
+
// ---- DOM storage factory ----------------------------------------
|
|
1484
1501
|
|
|
1485
1502
|
/**
|
|
1486
1503
|
* Build the {@link DomStorage} returned by `Page.localStorage` /
|
package/src/proc.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type { PipeReader, PipeWriter } from "./cdp/transport";
|
|
|
15
15
|
/**
|
|
16
16
|
* The chromium flags PLAN.md §8.6 mandates we always pass in PRODUCTION
|
|
17
17
|
* (non-hermetic) mode. Trimmed against patchright's
|
|
18
|
-
* `chromiumSwitchesPatch.ts:20-34` removal list
|
|
18
|
+
* `chromiumSwitchesPatch.ts:20-34` removal list: every flag
|
|
19
19
|
* here passes two tests — (a) it isn't a passive command-line bot-tell that
|
|
20
20
|
* patchright explicitly drops, AND (b) we have a concrete production reason
|
|
21
21
|
* to keep it (CDP transport, UI suppression that matters in headed mode,
|
|
@@ -181,7 +181,7 @@ export interface SpawnConfig {
|
|
|
181
181
|
* integers; otherwise the flag is omitted. Sourced from
|
|
182
182
|
* `matrix.display.{width,height}` by `launch.ts` — the matrix is canonical.
|
|
183
183
|
*
|
|
184
|
-
* @see UDC `__init__.py:410-411`, UDC issue #2242,
|
|
184
|
+
* @see UDC `__init__.py:410-411`, UDC issue #2242,
|
|
185
185
|
*/
|
|
186
186
|
windowSize?: { width: number; height: number };
|
|
187
187
|
/**
|
|
@@ -418,7 +418,7 @@ export function buildChromiumArgs(
|
|
|
418
418
|
}
|
|
419
419
|
// Headless dispatch.
|
|
420
420
|
//
|
|
421
|
-
// `headlessMode`
|
|
421
|
+
// `headlessMode` supersedes the legacy `headless: boolean` knob
|
|
422
422
|
// when both are set. When `headlessMode` is unset, fall back to the v0.1
|
|
423
423
|
// mapping (`headless: true → "new"`, `false → "off"`). The launcher in
|
|
424
424
|
// `launch.ts` is responsible for the env-aware default ("new" on Linux
|
|
@@ -445,7 +445,7 @@ export function buildChromiumArgs(
|
|
|
445
445
|
// header so the network surface matches the JS-layer `navigator.language`
|
|
446
446
|
// spoof (PLAN.md I-5). Pushed BEFORE `extraArgs` so a user-supplied
|
|
447
447
|
// override in `args` can win on the command line if absolutely needed —
|
|
448
|
-
// Chromium honors the last-occurrence on the line for `--lang`.
|
|
448
|
+
// Chromium honors the last-occurrence on the line for `--lang`.
|
|
449
449
|
if (cfg.locale !== undefined && cfg.locale.length > 0) {
|
|
450
450
|
args.push(`--lang=${cfg.locale}`);
|
|
451
451
|
}
|
|
@@ -454,7 +454,7 @@ export function buildChromiumArgs(
|
|
|
454
454
|
// Chromium's headless 800×600 default. The matrix is canonical: when
|
|
455
455
|
// `display.{width,height}` is missing or non-finite we omit the flag
|
|
456
456
|
// rather than fall back to a hardcoded value (a hardcoded value would
|
|
457
|
-
// mismatch a profile that legitimately uses different dimensions).
|
|
457
|
+
// mismatch a profile that legitimately uses different dimensions).
|
|
458
458
|
if (cfg.windowSize !== undefined) {
|
|
459
459
|
const { width, height } = cfg.windowSize;
|
|
460
460
|
if (
|
|
@@ -501,7 +501,6 @@ export function buildChromiumArgs(
|
|
|
501
501
|
* surfaces only the raw stderr tail. Exported for unit tests so we can lock
|
|
502
502
|
* the regexes against regressions without spawning Chromium.
|
|
503
503
|
*
|
|
504
|
-
* @see tasks/0259-linux-first-run-experience.md
|
|
505
504
|
*/
|
|
506
505
|
export function diagnoseEarlyExitTail(tail: string): string {
|
|
507
506
|
if (/running.*root.*without.*--no-sandbox|--no-sandbox.*required/i.test(tail)) {
|
package/src/proxy-auth.ts
CHANGED
|
@@ -39,8 +39,6 @@
|
|
|
39
39
|
* handler covers both.
|
|
40
40
|
*
|
|
41
41
|
* @see PLAN.md §8.2 / §10
|
|
42
|
-
* @see tasks/0160-proxy-auth-and-ci-fix.md
|
|
43
|
-
* @see tasks/0266-fetch-fulfill-init-script.md
|
|
44
42
|
*/
|
|
45
43
|
|
|
46
44
|
import { installInitInjector } from "./cdp/init-injector";
|
|
@@ -148,7 +146,7 @@ export interface ProxyAuthHandle {
|
|
|
148
146
|
* shim — delegates to {@link installInitInjector} with `payloadCode: null`
|
|
149
147
|
* so the proxy-auth-only call path still works for any out-of-tree caller.
|
|
150
148
|
*
|
|
151
|
-
* The Session no longer uses this directly
|
|
149
|
+
* The Session no longer uses this directly; proxy auth and
|
|
152
150
|
* init-script delivery share a single `Fetch.enable` owner.
|
|
153
151
|
*
|
|
154
152
|
* Behavior (unchanged contract):
|