sootsim 0.1.227 → 0.1.228
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 +14 -14
- package/detox/element-types.ts +3 -3
- package/detox/expectations.ts +29 -24
- package/detox/gestures.ts +16 -16
- package/detox/index.ts +34 -32
- package/dist-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-HBVXCRJT.js → agent-6P5T2QHC.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-X376DPV2.js → agent-wrapper-SMEMJZXI.js} +2 -2
- package/dist-cli/chunks/{app-fonts-LIQTD5RP.js → app-fonts-6OQTLX3U.js} +2 -2
- package/dist-cli/chunks/{assert-X6PPLN72.js → assert-ZAYFOW6R.js} +2 -2
- package/dist-cli/chunks/{auth-INRWIM2C.js → auth-Y53UANSH.js} +2 -2
- package/dist-cli/chunks/beta-ZQCASJ7C.js +2 -0
- package/dist-cli/chunks/{camera-LGFHYCJ5.js → camera-AJQWSOO4.js} +2 -2
- package/dist-cli/chunks/{chunk-2BQOZATN.js → chunk-2I62CFYI.js} +3 -3
- package/dist-cli/chunks/{chunk-E3DLUOFK.js → chunk-34MFG4IM.js} +7 -7
- package/dist-cli/chunks/{chunk-J7IFVTWX.js → chunk-4A6HM2K3.js} +1 -1
- package/dist-cli/chunks/chunk-4QOY4T27.js +3 -0
- package/dist-cli/chunks/{chunk-HRYKZ5YY.js → chunk-6Q2B7QHC.js} +5 -5
- package/dist-cli/chunks/{chunk-F5HOYUD2.js → chunk-6U3GMNTP.js} +1 -1
- package/dist-cli/chunks/{chunk-RNWJQ4UR.js → chunk-72AQH53U.js} +1 -1
- package/dist-cli/chunks/{chunk-NIN75M5H.js → chunk-7HMRWJHH.js} +1 -1
- package/dist-cli/chunks/{chunk-YB2LM6VB.js → chunk-7TJVPCQA.js} +6 -6
- package/dist-cli/chunks/{chunk-LM544J6V.js → chunk-A5SO4OGE.js} +1 -1
- package/dist-cli/chunks/{chunk-D42IRY2Y.js → chunk-AJ3CDBW6.js} +2 -2
- package/dist-cli/chunks/chunk-ALE5MU5Z.js +2 -0
- package/dist-cli/chunks/{chunk-NHE3YHDU.js → chunk-AVS7RL73.js} +2 -2
- package/dist-cli/chunks/chunk-AWF575Y5.js +1 -0
- package/dist-cli/chunks/chunk-BHNOPI7I.js +2 -0
- package/dist-cli/chunks/{chunk-LCJSTEIR.js → chunk-D2QUTBZP.js} +2 -2
- package/dist-cli/chunks/{chunk-ESK7B2BQ.js → chunk-DEVNCWS4.js} +6 -6
- package/dist-cli/chunks/{chunk-GUCFICA4.js → chunk-E5FOMYR6.js} +1 -1
- package/dist-cli/chunks/{chunk-2XXPF6LP.js → chunk-EFMPSG7T.js} +2 -2
- package/dist-cli/chunks/{chunk-4J7BIXEB.js → chunk-EKWOBYJO.js} +2 -2
- package/dist-cli/chunks/{chunk-E75EBS77.js → chunk-EPQ5EZBJ.js} +2 -2
- package/dist-cli/chunks/{chunk-Q4FB222M.js → chunk-FDSFA7WL.js} +3 -3
- package/dist-cli/chunks/{chunk-UGWURWHN.js → chunk-FSKQZHM2.js} +2 -2
- package/dist-cli/chunks/{chunk-QWRYD2QV.js → chunk-G42TLJVQ.js} +18 -18
- package/dist-cli/chunks/{chunk-HXHB5A6R.js → chunk-JA52F67H.js} +2 -2
- package/dist-cli/chunks/chunk-JKZY5CPQ.js +2 -0
- package/dist-cli/chunks/{chunk-MG6JE3AM.js → chunk-JV43GSZB.js} +2 -2
- package/dist-cli/chunks/{chunk-7L5IKIHC.js → chunk-JWZMAJC7.js} +1 -1
- package/dist-cli/chunks/{chunk-F53C5HAB.js → chunk-KIL5F7KD.js} +1 -1
- package/dist-cli/chunks/chunk-KY2KLPYL.js +1 -0
- package/dist-cli/chunks/{chunk-DB3GMVOH.js → chunk-LBXHG4AU.js} +2 -2
- package/dist-cli/chunks/{chunk-SBIAPF6E.js → chunk-MCMMRIJV.js} +1 -1
- package/dist-cli/chunks/{chunk-A4BOYB55.js → chunk-MWZOCZ7J.js} +2 -2
- package/dist-cli/chunks/{chunk-HXSV263V.js → chunk-NCXHUU7N.js} +1 -1
- package/dist-cli/chunks/{chunk-HTVB3FW2.js → chunk-NME4QWJ3.js} +2 -2
- package/dist-cli/chunks/{chunk-J2JAOIMN.js → chunk-OETQYAI2.js} +2 -2
- package/dist-cli/chunks/chunk-PJBYZZWR.js +2 -0
- package/dist-cli/chunks/{chunk-NU755HCE.js → chunk-PNPH4JLS.js} +1 -1
- package/dist-cli/chunks/chunk-RT3OS624.js +118 -0
- package/dist-cli/chunks/{chunk-7LDHOQ7B.js → chunk-SACWV3LZ.js} +20 -20
- package/dist-cli/chunks/chunk-SPJSTRXX.js +24 -0
- package/dist-cli/chunks/{chunk-3L5EXWCP.js → chunk-UYLESZU3.js} +1 -1
- package/dist-cli/chunks/{chunk-XESYTWFM.js → chunk-WWZL7HNB.js} +29 -29
- package/dist-cli/chunks/{chunk-T6MEERRI.js → chunk-ZBJ5JMXM.js} +2 -2
- package/dist-cli/chunks/chunk-ZWJEJR73.js +4 -0
- package/dist-cli/chunks/cli-version-V4GJYM74.js +2 -0
- package/dist-cli/chunks/{compat-MH673TEJ.js → compat-W7E4744D.js} +3 -3
- package/dist-cli/chunks/{config-SSCDV5ZJ.js → config-N7G65EY2.js} +2 -2
- package/dist-cli/chunks/{control-54R2XDLV.js → control-7VDFEVWU.js} +2 -2
- package/dist-cli/chunks/daemon-UI3PQ47F.js +2 -0
- package/dist-cli/chunks/{debug-PFP646II.js → debug-ZKUCSCOU.js} +3 -3
- package/dist-cli/chunks/{desktop-BPYYJ3EM.js → desktop-L3OXTT45.js} +3 -3
- package/dist-cli/chunks/{detox-BIUVHXYH.js → detox-QG4IBZAG.js} +2 -2
- package/dist-cli/chunks/{device-BNSPNIP6.js → device-QC6MDI7W.js} +2 -2
- package/dist-cli/chunks/{diagnose-BPTDSGOB.js → diagnose-HTUDENJK.js} +2 -2
- package/dist-cli/chunks/drivers-L2BXXDI7.js +2 -0
- package/dist-cli/chunks/{film-ILA6VSOG.js → film-CT7FHNLE.js} +3 -3
- package/dist-cli/chunks/flow-XUBXWJHL.js +2 -0
- package/dist-cli/chunks/help-7CIGANJN.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-TD7IVAPF.js → hidden-runtime-alias-YTUEPZ3U.js} +2 -2
- package/dist-cli/chunks/{home-paths-H36JDTNO.js → home-paths-7K6HDXOP.js} +2 -2
- package/dist-cli/chunks/inspect-ZY3QI7VJ.js +2 -0
- package/dist-cli/chunks/install-desktop-CVPRYFFV.js +2 -0
- package/dist-cli/chunks/{login-5WGZX2ZD.js → login-XHOOXAOW.js} +4 -4
- package/dist-cli/chunks/{logout-V53WTVIZ.js → logout-7BISNC5F.js} +2 -2
- package/dist-cli/chunks/{maestro-HGKYRD54.js → maestro-YD3G7LSG.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-6DNZSKDP.js → maestro-generate-WNOWZC5K.js} +3 -3
- package/dist-cli/chunks/{mode-YFMKORE5.js → mode-Y6JJMXU5.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-YUXURWKX.js +2 -0
- package/dist-cli/chunks/{perf-EOIGFDWM.js → perf-AY3ZKTDS.js} +2 -2
- package/dist-cli/chunks/{record-2F54QS6Y.js → record-ZC4W6QN6.js} +10 -10
- package/dist-cli/chunks/runtime-MVYAP3UX.js +2 -0
- package/dist-cli/chunks/screenshot-command-NRKTGTSJ.js +151 -0
- package/dist-cli/chunks/{screenshots-capture-DIICN24R.js → screenshots-capture-LZR3AHWN.js} +3 -3
- package/dist-cli/chunks/{serve-66NC6PPZ.js → serve-4X2WI5XF.js} +5 -5
- package/dist-cli/chunks/{setup-ZYN4BTBR.js → setup-KODPGJBJ.js} +3 -3
- package/dist-cli/chunks/{skills-MDBIER7U.js → skills-DEAUDOAN.js} +2 -2
- package/dist-cli/chunks/{storage-AQ3SEO4Y.js → storage-P7FQRH5T.js} +2 -2
- package/dist-cli/chunks/store-PTRXOHHV.js +2 -0
- package/dist-cli/chunks/telemetry-JHKOHSI2.js +2 -0
- package/dist-cli/chunks/{timeline-VEGHQZ36.js → timeline-7ISYXLR3.js} +2 -2
- package/dist-cli/chunks/{upgrade-RNDCRPLJ.js → upgrade-NZBJS5L2.js} +3 -3
- package/dist-cli/chunks/upload-J34H5SXV.js +2 -0
- package/dist-cli/chunks/{version-XUMPKQUM.js → version-J6BLGLTO.js} +2 -2
- package/dist-cli/chunks/{web-ESQGHVPD.js → web-Y6UVYM3Z.js} +2 -2
- package/dist-cli/chunks/{what-happened-6NJENKUF.js → what-happened-YKXXY6W2.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +2 -2
- package/dist-lib/backend-origin.cjs +18 -18
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +4 -4
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +321 -79
- package/dist-lib/dev-bundle-resolution.cjs +2 -2
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +18 -13
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +7 -7
- package/dist-lib/sdk.cjs +12 -4
- package/dist-lib/sdk.mjs +12 -4
- package/dist-lib/skills.cjs +425 -169
- package/dist-lib/vite.cjs +1 -1
- package/package.json +4 -4
- package/scripts/dev-server-scanner.ts +5 -5
- package/scripts/postinstall.cjs +1 -1
- package/scripts/preuninstall.cjs +1 -1
- package/skills/{soot → contrast}/SKILL.md +4 -4
- package/skills/sootsim-perf/SKILL.md +3 -1
- package/src/auth/shared-session.ts +1 -1
- package/src/backend-origin.ts +11 -11
- package/src/bridge-constants.ts +3 -3
- package/src/home-paths.ts +1 -1
- package/src/host/agent-host.ts +2 -2
- package/src/host/bridge-host.ts +21 -21
- package/src/native-dev-bundle-url.ts +3 -3
- package/src/runtime-assets.ts +3 -3
- package/src/runtime-delivery.ts +10 -4
- package/src/screenshots/compose.ts +4 -1
- package/src/screenshots/frame-compose.ts +4 -1
- package/src/screenshots/orchestrate.ts +7 -2
- package/src/vite-plugin-one.ts +3 -3
- package/src/vite-plugin.ts +3 -3
- package/dist-cli/chunks/beta-WLLSIVLW.js +0 -2
- package/dist-cli/chunks/chunk-35EAEAN4.js +0 -24
- package/dist-cli/chunks/chunk-44Z2X5R4.js +0 -2
- package/dist-cli/chunks/chunk-4BLOZ3AF.js +0 -2
- package/dist-cli/chunks/chunk-7K5K5NKB.js +0 -2
- package/dist-cli/chunks/chunk-7RWDQCIT.js +0 -1
- package/dist-cli/chunks/chunk-BVD2JFOX.js +0 -1
- package/dist-cli/chunks/chunk-HBEEYWK5.js +0 -2
- package/dist-cli/chunks/chunk-JNUGPBWC.js +0 -118
- package/dist-cli/chunks/chunk-KBSJA7HK.js +0 -3
- package/dist-cli/chunks/chunk-Z2E2DDIQ.js +0 -4
- package/dist-cli/chunks/cli-version-NNBCIQKL.js +0 -2
- package/dist-cli/chunks/daemon-GL5GQTWB.js +0 -2
- package/dist-cli/chunks/drivers-KBKJVF2Y.js +0 -2
- package/dist-cli/chunks/flow-L247VVBM.js +0 -2
- package/dist-cli/chunks/help-QIZEANNK.js +0 -2
- package/dist-cli/chunks/inspect-6OAVS27G.js +0 -2
- package/dist-cli/chunks/install-desktop-LKYAUUQY.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-YGNESGBH.js +0 -2
- package/dist-cli/chunks/runtime-FYVV4DCQ.js +0 -2
- package/dist-cli/chunks/screenshot-command-R535TYXY.js +0 -151
- package/dist-cli/chunks/store-6ZGLOTZI.js +0 -2
- package/dist-cli/chunks/telemetry-V76UPVDV.js +0 -2
- package/dist-cli/chunks/upload-KRBS3Y7Q.js +0 -2
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.228 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -32,6 +32,389 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
));
|
|
33
33
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
34
34
|
|
|
35
|
+
// ../../scripts/lib/reap-browser.ts
|
|
36
|
+
function currentRuntime() {
|
|
37
|
+
return { platform: process.platform, env: process.env };
|
|
38
|
+
}
|
|
39
|
+
function softwareChromeAllowed(runtime = currentRuntime()) {
|
|
40
|
+
return runtime.platform === "linux" && runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux";
|
|
41
|
+
}
|
|
42
|
+
function isSoftwareRendererArgument(value) {
|
|
43
|
+
const arg = String(value);
|
|
44
|
+
return /^--disable-gpu(?:=.*)?$/i.test(arg) || /^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg) || /^--use-angle=(?:swiftshader|swiftshader-webgl)$/i.test(arg) || /^--use-gl=swiftshader$/i.test(arg);
|
|
45
|
+
}
|
|
46
|
+
function softwareRendererArgumentInText(command) {
|
|
47
|
+
const unsafe = command.match(
|
|
48
|
+
/(?:^|\s)(--disable-gpu(?:=[^\s]+)?|--enable-unsafe-swiftshader(?:=[^\s]+)?|--use-angle=(?:swiftshader|swiftshader-webgl)|--use-gl=swiftshader)(?=\s|$)/i
|
|
49
|
+
);
|
|
50
|
+
return unsafe?.[1] ?? null;
|
|
51
|
+
}
|
|
52
|
+
function expectedAngle(platform) {
|
|
53
|
+
if (platform === "darwin") return "metal";
|
|
54
|
+
if (platform === "linux") return "vulkan";
|
|
55
|
+
return "default";
|
|
56
|
+
}
|
|
57
|
+
function assertGpuBrowserCommand(command, runtime = currentRuntime()) {
|
|
58
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
59
|
+
const unsafe = softwareRendererArgumentInText(command);
|
|
60
|
+
if (unsafe) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`[reap-browser] refused software-rendering Chrome process argument ${unsafe}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const angle = expectedAngle(runtime.platform);
|
|
66
|
+
const args = command.split(/\s+/);
|
|
67
|
+
if (!args.includes(`--use-angle=${angle}`) || !args.includes("--enable-gpu")) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`[reap-browser] Chrome process did not retain the required ${angle} GPU arguments`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (runtime.platform === "darwin" && command.includes("/Applications/Google Chrome.app/")) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"[reap-browser] refused the user's installed Google Chrome; use Playwright channel chromium"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function collectGpuRendererStrings(info) {
|
|
79
|
+
if (!info || typeof info !== "object") return [];
|
|
80
|
+
const record = info;
|
|
81
|
+
const gpu = record.gpu;
|
|
82
|
+
if (!gpu || typeof gpu !== "object") return [];
|
|
83
|
+
const gpuRecord = gpu;
|
|
84
|
+
const values = [];
|
|
85
|
+
const aux = gpuRecord.auxAttributes;
|
|
86
|
+
if (aux && typeof aux === "object") {
|
|
87
|
+
for (const value of Object.values(aux)) {
|
|
88
|
+
if (typeof value === "string") values.push(value);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const devices2 = gpuRecord.devices;
|
|
92
|
+
if (Array.isArray(devices2)) {
|
|
93
|
+
for (const device of devices2) {
|
|
94
|
+
if (!device || typeof device !== "object") continue;
|
|
95
|
+
for (const value of Object.values(device)) {
|
|
96
|
+
if (typeof value === "string") values.push(value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return values;
|
|
101
|
+
}
|
|
102
|
+
function browserProcessPid(info) {
|
|
103
|
+
if (!info || typeof info !== "object") return null;
|
|
104
|
+
const record = info;
|
|
105
|
+
if (!Array.isArray(record.processInfo)) return null;
|
|
106
|
+
for (const entry of record.processInfo) {
|
|
107
|
+
if (!entry || typeof entry !== "object") continue;
|
|
108
|
+
const processInfo = entry;
|
|
109
|
+
if (processInfo.type === "browser" && typeof processInfo.id === "number" && Number.isInteger(processInfo.id) && processInfo.id > 0) {
|
|
110
|
+
return processInfo.id;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function assertGpuRendererInfo(info, runtime = currentRuntime()) {
|
|
116
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
117
|
+
const renderers = collectGpuRendererStrings(info);
|
|
118
|
+
const summary = renderers.join(" | ");
|
|
119
|
+
if (!summary || /swiftshader|llvmpipe|software rasterizer/i.test(summary)) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`[reap-browser] Chrome reported a software renderer${summary ? `: ${summary}` : ""}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (runtime.platform === "darwin" && !/metal/i.test(summary)) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`[reap-browser] Chrome did not report an ANGLE Metal renderer: ${summary}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function rootChromePid(b) {
|
|
131
|
+
if (b && typeof b === "object") {
|
|
132
|
+
const discovered = discoveredChromePids.get(b);
|
|
133
|
+
if (discovered !== void 0) return discovered;
|
|
134
|
+
}
|
|
135
|
+
const w = b;
|
|
136
|
+
if (w && typeof w.process === "function") {
|
|
137
|
+
try {
|
|
138
|
+
const p = w.process();
|
|
139
|
+
if (p && typeof p.pid === "number" && p.pid > 0) return p.pid;
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (w && typeof w.browser === "function") {
|
|
144
|
+
try {
|
|
145
|
+
const child = w.browser();
|
|
146
|
+
if (child) return rootChromePid(child);
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function killTree(pid) {
|
|
153
|
+
let kids = [];
|
|
154
|
+
try {
|
|
155
|
+
kids = (0, import_node_child_process.execSync)(`pgrep -P ${pid} || true`).toString().split("\n").filter(Boolean);
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
for (const k of kids) killTree(Number(k));
|
|
159
|
+
try {
|
|
160
|
+
process.kill(pid, "SIGKILL");
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function browserControl(b) {
|
|
165
|
+
const candidate = b;
|
|
166
|
+
if (!candidate || typeof candidate !== "object") return null;
|
|
167
|
+
if (typeof candidate.newBrowserCDPSession === "function" || typeof candidate.process === "function") {
|
|
168
|
+
return candidate;
|
|
169
|
+
}
|
|
170
|
+
if (typeof candidate.browser !== "function") return null;
|
|
171
|
+
try {
|
|
172
|
+
const browser = candidate.browser();
|
|
173
|
+
return browser ? browserControl(browser) : null;
|
|
174
|
+
} catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function registerChromePid(browser, control, pid) {
|
|
179
|
+
if (browser && typeof browser === "object") discoveredChromePids.set(browser, pid);
|
|
180
|
+
discoveredChromePids.set(control, pid);
|
|
181
|
+
reapPids.add(pid);
|
|
182
|
+
installReaper();
|
|
183
|
+
}
|
|
184
|
+
async function discoverChromePid(browser) {
|
|
185
|
+
const known = rootChromePid(browser);
|
|
186
|
+
if (known !== null) return known;
|
|
187
|
+
const control = browserControl(browser);
|
|
188
|
+
if (!control || typeof control.newBrowserCDPSession !== "function") return null;
|
|
189
|
+
const session = await control.newBrowserCDPSession();
|
|
190
|
+
try {
|
|
191
|
+
const pid = browserProcessPid(await session.send("SystemInfo.getProcessInfo"));
|
|
192
|
+
if (pid === null) return null;
|
|
193
|
+
registerChromePid(browser, control, pid);
|
|
194
|
+
return pid;
|
|
195
|
+
} finally {
|
|
196
|
+
await session.detach?.();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function rejectLaunchedBrowser(browser) {
|
|
200
|
+
const root = rootChromePid(browser);
|
|
201
|
+
if (root !== null) {
|
|
202
|
+
reapPids.delete(root);
|
|
203
|
+
killTree(root);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const candidate = browser;
|
|
207
|
+
if (candidate && typeof candidate.close === "function") {
|
|
208
|
+
try {
|
|
209
|
+
await candidate.close();
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async function validateLaunchedGpuBrowser(browser, runtime, rendererTarget) {
|
|
215
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
216
|
+
const root = rootChromePid(browser);
|
|
217
|
+
const launchedControl = browserControl(browser);
|
|
218
|
+
if (root !== null && launchedControl) {
|
|
219
|
+
registerChromePid(browser, launchedControl, root);
|
|
220
|
+
}
|
|
221
|
+
if (root !== null && (runtime.platform === "darwin" || runtime.platform === "linux")) {
|
|
222
|
+
const command = (0, import_node_child_process.execFileSync)("ps", ["-p", String(root), "-o", "command="], {
|
|
223
|
+
encoding: "utf8"
|
|
224
|
+
}).trim();
|
|
225
|
+
assertGpuBrowserCommand(command, runtime);
|
|
226
|
+
}
|
|
227
|
+
const rendererBrowser = rendererTarget ? await rendererTarget(browser) : browser;
|
|
228
|
+
const control = browserControl(rendererBrowser);
|
|
229
|
+
if (control && typeof control.newBrowserCDPSession === "function") {
|
|
230
|
+
const session = await control.newBrowserCDPSession();
|
|
231
|
+
try {
|
|
232
|
+
const pid = browserProcessPid(await session.send("SystemInfo.getProcessInfo"));
|
|
233
|
+
if (pid === null) {
|
|
234
|
+
throw new Error("[reap-browser] Chrome did not report its browser process id");
|
|
235
|
+
}
|
|
236
|
+
registerChromePid(browser, control, pid);
|
|
237
|
+
if (rendererBrowser && typeof rendererBrowser === "object") {
|
|
238
|
+
discoveredChromePids.set(rendererBrowser, pid);
|
|
239
|
+
}
|
|
240
|
+
if (runtime.platform === "darwin" || runtime.platform === "linux") {
|
|
241
|
+
const command = (0, import_node_child_process.execFileSync)("ps", ["-p", String(pid), "-o", "command="], {
|
|
242
|
+
encoding: "utf8"
|
|
243
|
+
}).trim();
|
|
244
|
+
assertGpuBrowserCommand(command, runtime);
|
|
245
|
+
}
|
|
246
|
+
assertGpuRendererInfo(await session.send("SystemInfo.getInfo"), runtime);
|
|
247
|
+
return;
|
|
248
|
+
} finally {
|
|
249
|
+
await session.detach?.();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
throw new Error("[reap-browser] could not validate the launched Chrome GPU renderer");
|
|
253
|
+
}
|
|
254
|
+
function installReaper() {
|
|
255
|
+
if (installed) return;
|
|
256
|
+
installed = true;
|
|
257
|
+
const reap = () => {
|
|
258
|
+
for (const pid of reapPids) killTree(pid);
|
|
259
|
+
};
|
|
260
|
+
process.on("SIGTERM", () => {
|
|
261
|
+
reap();
|
|
262
|
+
process.exit(0);
|
|
263
|
+
});
|
|
264
|
+
process.on("SIGINT", () => {
|
|
265
|
+
reap();
|
|
266
|
+
process.exit(0);
|
|
267
|
+
});
|
|
268
|
+
process.on("exit", reap);
|
|
269
|
+
}
|
|
270
|
+
async function launchReapedScoped(launch) {
|
|
271
|
+
const browser = await launch();
|
|
272
|
+
let root = rootChromePid(browser);
|
|
273
|
+
if (root === null) {
|
|
274
|
+
try {
|
|
275
|
+
root = await discoverChromePid(browser);
|
|
276
|
+
} catch {
|
|
277
|
+
root = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const mine = /* @__PURE__ */ new Set();
|
|
281
|
+
if (root != null) {
|
|
282
|
+
mine.add(root);
|
|
283
|
+
reapPids.add(root);
|
|
284
|
+
installReaper();
|
|
285
|
+
}
|
|
286
|
+
const evented = browserControl(browser) ?? browser;
|
|
287
|
+
if (typeof evented.on === "function") {
|
|
288
|
+
const disconnectEvent = typeof evented.newBrowserCDPSession === "function" ? "disconnected" : "close";
|
|
289
|
+
evented.on(disconnectEvent, () => {
|
|
290
|
+
for (const pid of mine) reapPids.delete(pid);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
const reapNow = () => {
|
|
294
|
+
for (const pid of mine) {
|
|
295
|
+
killTree(pid);
|
|
296
|
+
reapPids.delete(pid);
|
|
297
|
+
}
|
|
298
|
+
mine.clear();
|
|
299
|
+
};
|
|
300
|
+
return { browser, reapNow };
|
|
301
|
+
}
|
|
302
|
+
async function launchReaped(launch) {
|
|
303
|
+
const { browser } = await launchReapedScoped(launch);
|
|
304
|
+
return browser;
|
|
305
|
+
}
|
|
306
|
+
function gpuChromeArgs(platform = process.platform) {
|
|
307
|
+
const angle = expectedAngle(platform);
|
|
308
|
+
return [
|
|
309
|
+
`--use-angle=${angle}`,
|
|
310
|
+
"--enable-gpu",
|
|
311
|
+
"--enable-gpu-rasterization",
|
|
312
|
+
"--enable-zero-copy",
|
|
313
|
+
"--ignore-gpu-blocklist"
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
|
|
317
|
+
const callerArgs = Array.isArray(opts.args) ? opts.args : [];
|
|
318
|
+
const unsafe = callerArgs.find(isSoftwareRendererArgument);
|
|
319
|
+
if (unsafe !== void 0) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
`[reap-browser] refused software-rendering Chrome launch argument ${String(unsafe)}`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (opts.executablePath !== void 0) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
"[reap-browser] executablePath bypasses Playwright Chrome for Testing and is not allowed"
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
if (opts.ignoreDefaultArgs === true) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
"[reap-browser] ignoreDefaultArgs=true bypasses required Chrome launch defaults"
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
const managedGpuArgs = /* @__PURE__ */ new Set([
|
|
335
|
+
"--enable-gpu",
|
|
336
|
+
"--enable-gpu-rasterization",
|
|
337
|
+
"--enable-zero-copy",
|
|
338
|
+
"--ignore-gpu-blocklist"
|
|
339
|
+
]);
|
|
340
|
+
const unmanagedCallerArgs = callerArgs.filter((arg) => {
|
|
341
|
+
const value = String(arg);
|
|
342
|
+
return !managedGpuArgs.has(value) && !value.startsWith("--use-angle=");
|
|
343
|
+
});
|
|
344
|
+
const callerIgnored = Array.isArray(opts.ignoreDefaultArgs) ? opts.ignoreDefaultArgs : [];
|
|
345
|
+
const ignoredDefaults = [
|
|
346
|
+
.../* @__PURE__ */ new Set([...callerIgnored, "--disable-gpu", "--enable-unsafe-swiftshader"])
|
|
347
|
+
];
|
|
348
|
+
return {
|
|
349
|
+
...opts,
|
|
350
|
+
// playwright's `chromium` channel is the full Google Chrome for Testing
|
|
351
|
+
// app, not chromium_headless_shell. on macOS it has bundle id
|
|
352
|
+
// com.google.chrome.for.testing, so automation cannot become the target of
|
|
353
|
+
// Dock open/quit events intended for the user's com.google.Chrome browser.
|
|
354
|
+
channel: "chromium",
|
|
355
|
+
args: [...unmanagedCallerArgs, ...gpuChromeArgs(runtime.platform)],
|
|
356
|
+
ignoreDefaultArgs: ignoredDefaults
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function preferGpuChrome(launch, opts, rendererTarget) {
|
|
360
|
+
return async () => {
|
|
361
|
+
const runtime = currentRuntime();
|
|
362
|
+
const allowSoftwareFallback = softwareChromeAllowed(runtime);
|
|
363
|
+
const gpuOptions = gpuChromeLaunchOptions(opts, runtime);
|
|
364
|
+
if (!gpuChromeMissing) {
|
|
365
|
+
let browser;
|
|
366
|
+
try {
|
|
367
|
+
browser = await launch(gpuOptions);
|
|
368
|
+
} catch (err) {
|
|
369
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
370
|
+
const missing = /not found at|not installed|Chromium distribution|Executable doesn't exist|No such file/i.test(
|
|
371
|
+
msg
|
|
372
|
+
);
|
|
373
|
+
if (!missing) throw err;
|
|
374
|
+
if (!allowSoftwareFallback) {
|
|
375
|
+
throw new Error(
|
|
376
|
+
"[reap-browser] Playwright Chrome for Testing is required for local GPU browser work; chromium_headless_shell fallback is disabled. Run `bunx playwright install chromium`.",
|
|
377
|
+
{ cause: err }
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
gpuChromeMissing = true;
|
|
381
|
+
console.warn(
|
|
382
|
+
"[reap-browser] GitHub Actions Linux Chrome for Testing not found, falling back to chromium_headless_shell software rendering."
|
|
383
|
+
);
|
|
384
|
+
return launch(softwareFallbackChromeLaunchOptions(opts));
|
|
385
|
+
}
|
|
386
|
+
try {
|
|
387
|
+
await validateLaunchedGpuBrowser(browser, runtime, rendererTarget);
|
|
388
|
+
} catch (err) {
|
|
389
|
+
await rejectLaunchedBrowser(browser);
|
|
390
|
+
throw err;
|
|
391
|
+
}
|
|
392
|
+
return browser;
|
|
393
|
+
}
|
|
394
|
+
return launch(softwareFallbackChromeLaunchOptions(opts));
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function softwareFallbackChromeLaunchOptions(opts) {
|
|
398
|
+
const fallback = { ...opts };
|
|
399
|
+
delete fallback.channel;
|
|
400
|
+
delete fallback.executablePath;
|
|
401
|
+
return fallback;
|
|
402
|
+
}
|
|
403
|
+
async function launchReapedChrome(launch, opts = {}, rendererTarget) {
|
|
404
|
+
return launchReaped(preferGpuChrome(launch, opts, rendererTarget));
|
|
405
|
+
}
|
|
406
|
+
var import_node_child_process, discoveredChromePids, reapPids, installed, gpuChromeMissing;
|
|
407
|
+
var init_reap_browser = __esm({
|
|
408
|
+
"../../scripts/lib/reap-browser.ts"() {
|
|
409
|
+
"use strict";
|
|
410
|
+
import_node_child_process = require("node:child_process");
|
|
411
|
+
discoveredChromePids = /* @__PURE__ */ new WeakMap();
|
|
412
|
+
reapPids = /* @__PURE__ */ new Set();
|
|
413
|
+
installed = false;
|
|
414
|
+
gpuChromeMissing = false;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
35
418
|
// ../compat/src/unsupported-packages.ts
|
|
36
419
|
var UNSUPPORTABLE;
|
|
37
420
|
var init_unsupported_packages = __esm({
|
|
@@ -9980,7 +10363,7 @@ function resolveSootsimBridgePortForRuntimeLocation(input = {}) {
|
|
|
9980
10363
|
if (hrefUrl?.pathname.startsWith("/sootsim") && (hrefUrl.searchParams.has("embed") || hrefUrl.searchParams.has("nativePreview"))) {
|
|
9981
10364
|
return resolveSootsimBridgePortForHttpPort({
|
|
9982
10365
|
httpPort,
|
|
9983
|
-
baseHttpPort:
|
|
10366
|
+
baseHttpPort: CONTRAST_DEV_HTTP_BASE_PORT
|
|
9984
10367
|
});
|
|
9985
10368
|
}
|
|
9986
10369
|
if (hrefUrl?.pathname.startsWith("/sootsim") && httpPort >= SOOTSIM_SITE_DEV_HTTP_BASE_PORT && httpPort <= SOOTSIM_SITE_DEV_HTTP_BASE_PORT + MAX_LOCAL_DEV_PORT_OFFSET) {
|
|
@@ -9993,16 +10376,16 @@ function resolveSootsimBridgePortForRuntimeLocation(input = {}) {
|
|
|
9993
10376
|
if (baseHttpPort === null) return DEFAULT_SOOTSIM_BRIDGE_PORT;
|
|
9994
10377
|
return resolveSootsimBridgePortForHttpPort({ httpPort, baseHttpPort });
|
|
9995
10378
|
}
|
|
9996
|
-
var DEFAULT_SOOTSIM_BRIDGE_PORT,
|
|
10379
|
+
var DEFAULT_SOOTSIM_BRIDGE_PORT, CONTRAST_DEV_HTTP_BASE_PORT, SOOTSIM_SITE_DEV_HTTP_BASE_PORT, SOOTSIM_SHELL_DEV_HTTP_BASE_PORT, LOCAL_DEV_HTTP_BASE_PORTS, MAX_LOCAL_DEV_PORT_OFFSET, SOOTSIM_BRIDGE_SIM_CLOSE_CODE, SOOTSIM_BRIDGE_SIM_CLOSE_REASON;
|
|
9997
10380
|
var init_bridge_constants = __esm({
|
|
9998
10381
|
"src/bridge-constants.ts"() {
|
|
9999
10382
|
"use strict";
|
|
10000
10383
|
DEFAULT_SOOTSIM_BRIDGE_PORT = 7668;
|
|
10001
|
-
|
|
10384
|
+
CONTRAST_DEV_HTTP_BASE_PORT = 3e3;
|
|
10002
10385
|
SOOTSIM_SITE_DEV_HTTP_BASE_PORT = 3001;
|
|
10003
10386
|
SOOTSIM_SHELL_DEV_HTTP_BASE_PORT = 5173;
|
|
10004
10387
|
LOCAL_DEV_HTTP_BASE_PORTS = [
|
|
10005
|
-
|
|
10388
|
+
CONTRAST_DEV_HTTP_BASE_PORT,
|
|
10006
10389
|
SOOTSIM_SHELL_DEV_HTTP_BASE_PORT
|
|
10007
10390
|
];
|
|
10008
10391
|
MAX_LOCAL_DEV_PORT_OFFSET = 2e3;
|
|
@@ -10052,7 +10435,7 @@ function applyPreviewProdBundle(parsed) {
|
|
|
10052
10435
|
function normalizeNativeDevBundleUrl(bundleUrl) {
|
|
10053
10436
|
try {
|
|
10054
10437
|
const isAbsolute2 = isAbsoluteHttpUrl(bundleUrl);
|
|
10055
|
-
const parsed = new URL(bundleUrl, "http://
|
|
10438
|
+
const parsed = new URL(bundleUrl, "http://sootsim.local");
|
|
10056
10439
|
parsed.pathname = parsed.pathname.replace(/\.\.bundle$/, ".bundle");
|
|
10057
10440
|
if (!isNativeDevBundlePath(parsed.pathname)) return bundleUrl;
|
|
10058
10441
|
parsed.searchParams.delete("transform.bytecode");
|
|
@@ -10419,7 +10802,7 @@ async function probePort(port, buildIconProxyUrl) {
|
|
|
10419
10802
|
knownNonPatched.add(port);
|
|
10420
10803
|
return null;
|
|
10421
10804
|
}
|
|
10422
|
-
function
|
|
10805
|
+
function isSootSimSelfServer(server) {
|
|
10423
10806
|
const bundleId = server.bundleId?.trim().toLowerCase();
|
|
10424
10807
|
if (bundleId?.startsWith("dev.sootsim.")) return true;
|
|
10425
10808
|
return false;
|
|
@@ -10503,7 +10886,7 @@ async function scanDevServers(opts = {}) {
|
|
|
10503
10886
|
for (const pid of [...cwdByPid.keys()]) {
|
|
10504
10887
|
if (!livePids.has(pid)) cwdByPid.delete(pid);
|
|
10505
10888
|
}
|
|
10506
|
-
return results.filter((r) => !
|
|
10889
|
+
return results.filter((r) => !isSootSimSelfServer(r));
|
|
10507
10890
|
}
|
|
10508
10891
|
var import_child_process, import_http, import_net, import_util, execP, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, FALLBACK_PORTS, cwdByPid, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
10509
10892
|
var init_dev_server_scanner = __esm({
|
|
@@ -10981,7 +11364,12 @@ async function updateRuntimeToLatest(opts = {}) {
|
|
|
10981
11364
|
latestVersion: pin
|
|
10982
11365
|
};
|
|
10983
11366
|
}
|
|
10984
|
-
const install2 = await installRuntime({
|
|
11367
|
+
const install2 = await installRuntime({
|
|
11368
|
+
version: pin,
|
|
11369
|
+
channel,
|
|
11370
|
+
cdnOrigin,
|
|
11371
|
+
setActive: false
|
|
11372
|
+
});
|
|
10985
11373
|
return {
|
|
10986
11374
|
checked: true,
|
|
10987
11375
|
updated: true,
|
|
@@ -11091,7 +11479,7 @@ var init_runtime_delivery = __esm({
|
|
|
11091
11479
|
import_stream = require("stream");
|
|
11092
11480
|
import_promises = require("stream/promises");
|
|
11093
11481
|
init_home_paths();
|
|
11094
|
-
DEFAULT_RUNTIME_CDN_ORIGIN = "https://
|
|
11482
|
+
DEFAULT_RUNTIME_CDN_ORIGIN = "https://contrast.dev";
|
|
11095
11483
|
RUNTIME_CDN_ORIGIN_ENV = "SOOTSIM_CDN_ORIGIN";
|
|
11096
11484
|
RUNTIME_CHANNEL_ENV = "SOOTSIM_RUNTIME_CHANNEL";
|
|
11097
11485
|
RUNTIME_PIN_ENV = "SOOTSIM_RUNTIME_VERSION";
|
|
@@ -13046,7 +13434,7 @@ function shouldAcquireLease(msg) {
|
|
|
13046
13434
|
if (msg.readOnly === true) return false;
|
|
13047
13435
|
return WRITE_COMMAND_TYPES.has(msg.type);
|
|
13048
13436
|
}
|
|
13049
|
-
function injectSharedConfigIntoHtml(data, bridgePort,
|
|
13437
|
+
function injectSharedConfigIntoHtml(data, bridgePort, contrastOrigin) {
|
|
13050
13438
|
let payload;
|
|
13051
13439
|
try {
|
|
13052
13440
|
const cfg = readSharedConfig();
|
|
@@ -13055,8 +13443,8 @@ function injectSharedConfigIntoHtml(data, bridgePort, sootbeanOrigin) {
|
|
|
13055
13443
|
payload = "{}";
|
|
13056
13444
|
}
|
|
13057
13445
|
const bridgePortTag = bridgePort > 0 ? `window.__sootsimBridgePort=${bridgePort};` : "";
|
|
13058
|
-
const
|
|
13059
|
-
const tag = `<script>window.__sootsimSharedConfig=${payload};` + bridgePortTag +
|
|
13446
|
+
const contrastOriginTag = contrastOrigin ? `window.__sootsimContrastOrigin=${JSON.stringify(contrastOrigin)};` : "";
|
|
13447
|
+
const tag = `<script>window.__sootsimSharedConfig=${payload};` + bridgePortTag + contrastOriginTag + `window.__sootsimCliVersion=${JSON.stringify(getCliVersion())};</script>`;
|
|
13060
13448
|
const html = data.toString("utf8");
|
|
13061
13449
|
if (html.includes("<head>")) return html.replace("<head>", `<head>${tag}`);
|
|
13062
13450
|
if (html.includes("</head>")) return html.replace("</head>", tag + "</head>");
|
|
@@ -13176,7 +13564,7 @@ var init_bridge_host = __esm({
|
|
|
13176
13564
|
shouldWriteLockfile;
|
|
13177
13565
|
shouldWriteDevLockfile;
|
|
13178
13566
|
getShellPort;
|
|
13179
|
-
|
|
13567
|
+
contrastOrigin = null;
|
|
13180
13568
|
effectivePort = 0;
|
|
13181
13569
|
startedAt = 0;
|
|
13182
13570
|
heartbeatTimer = null;
|
|
@@ -13223,7 +13611,7 @@ var init_bridge_host = __esm({
|
|
|
13223
13611
|
} : null;
|
|
13224
13612
|
}
|
|
13225
13613
|
});
|
|
13226
|
-
this.
|
|
13614
|
+
this.contrastOrigin = opts.contrastOrigin?.replace(/\/$/, "") || null;
|
|
13227
13615
|
this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
|
|
13228
13616
|
this.automationSimIdleReapTtlMs = opts.automationSimIdleReapTtlMs ?? _SootSimBridgeHost.AUTOMATION_SIM_IDLE_REAP_TTL_MS;
|
|
13229
13617
|
this.maxConcurrentAutomationSims = opts.maxConcurrentAutomationSims ?? _SootSimBridgeHost.MAX_CONCURRENT_AUTOMATION_SIMS;
|
|
@@ -14201,7 +14589,7 @@ var init_bridge_host = __esm({
|
|
|
14201
14589
|
return;
|
|
14202
14590
|
}
|
|
14203
14591
|
res.end(
|
|
14204
|
-
injectSharedConfigIntoHtml(data, this.effectivePort, this.
|
|
14592
|
+
injectSharedConfigIntoHtml(data, this.effectivePort, this.contrastOrigin)
|
|
14205
14593
|
);
|
|
14206
14594
|
});
|
|
14207
14595
|
return;
|
|
@@ -14226,7 +14614,7 @@ var init_bridge_host = __esm({
|
|
|
14226
14614
|
return;
|
|
14227
14615
|
}
|
|
14228
14616
|
res.end(
|
|
14229
|
-
injectSharedConfigIntoHtml(data, this.effectivePort, this.
|
|
14617
|
+
injectSharedConfigIntoHtml(data, this.effectivePort, this.contrastOrigin)
|
|
14230
14618
|
);
|
|
14231
14619
|
});
|
|
14232
14620
|
return;
|
|
@@ -15469,14 +15857,15 @@ function createBridge(wsPort, opts = {}) {
|
|
|
15469
15857
|
ws.send(JSON.stringify(payload));
|
|
15470
15858
|
});
|
|
15471
15859
|
};
|
|
15860
|
+
const sentSimId = opts.simIdSource === "flag" ? opts.simId : readCurrentSimId() ?? opts.simId;
|
|
15472
15861
|
try {
|
|
15473
|
-
return await sendOnce(
|
|
15862
|
+
return await sendOnce(sentSimId);
|
|
15474
15863
|
} catch (error) {
|
|
15475
15864
|
const message = error instanceof Error ? error.message : String(error);
|
|
15476
|
-
if (opts.simIdSource
|
|
15865
|
+
if (opts.simIdSource !== "flag" && sentSimId && cmd.simId === void 0 && message === `no sim connected with id ${sentSimId}`) {
|
|
15477
15866
|
clearCurrentSimId();
|
|
15478
15867
|
throw new Error(
|
|
15479
|
-
`saved sim ${
|
|
15868
|
+
`saved sim ${sentSimId} is gone; run \`sootsim list\` and \`sootsim use <sim>\`, or open a fresh sim`
|
|
15480
15869
|
);
|
|
15481
15870
|
}
|
|
15482
15871
|
throw error;
|
|
@@ -15872,7 +16261,9 @@ function renderFrameHtml(layout, rawImageDataUrl) {
|
|
|
15872
16261
|
}
|
|
15873
16262
|
async function composeFramedScreenshot(rawPng, model) {
|
|
15874
16263
|
const { chromium } = await import("playwright");
|
|
15875
|
-
const browser = await chromium.launch({
|
|
16264
|
+
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
16265
|
+
headless: true
|
|
16266
|
+
});
|
|
15876
16267
|
try {
|
|
15877
16268
|
const composer = await createFramedScreenshotComposer(browser);
|
|
15878
16269
|
try {
|
|
@@ -15932,6 +16323,7 @@ var init_frame_compose = __esm({
|
|
|
15932
16323
|
"use strict";
|
|
15933
16324
|
import_chrome_metrics = require("sootsim-engine/ios/chrome-metrics");
|
|
15934
16325
|
import_settings = require("sootsim-engine/settings");
|
|
16326
|
+
init_reap_browser();
|
|
15935
16327
|
METALLIC_RING_SHADOW = "inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121";
|
|
15936
16328
|
FRAME_OUTLINE_BLEED = 1;
|
|
15937
16329
|
}
|
|
@@ -16712,7 +17104,7 @@ var init_shared_session = __esm({
|
|
|
16712
17104
|
init_home_paths();
|
|
16713
17105
|
SESSION_VERSION = 1;
|
|
16714
17106
|
SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
16715
|
-
DEFAULT_ORIGIN = "https://
|
|
17107
|
+
DEFAULT_ORIGIN = "https://contrast.dev";
|
|
16716
17108
|
}
|
|
16717
17109
|
});
|
|
16718
17110
|
|
|
@@ -16723,15 +17115,15 @@ function looksLikeGitHubToken(token) {
|
|
|
16723
17115
|
);
|
|
16724
17116
|
}
|
|
16725
17117
|
function resolveGitHubActionsAuth() {
|
|
16726
|
-
const
|
|
17118
|
+
const contrastRunnerToken = process.env.CONTRAST_INSTALLATION_TOKEN?.trim();
|
|
16727
17119
|
const githubActionsToken = process.env.GITHUB_TOKEN?.trim();
|
|
16728
|
-
const token =
|
|
17120
|
+
const token = contrastRunnerToken || githubActionsToken;
|
|
16729
17121
|
if (!looksLikeGitHubToken(token)) return null;
|
|
16730
|
-
const repoSlug = (process.env.
|
|
17122
|
+
const repoSlug = (process.env.CONTRAST_REPO || process.env.GITHUB_REPOSITORY || "").trim();
|
|
16731
17123
|
if (!repoSlug) return null;
|
|
16732
17124
|
const [owner, repo] = repoSlug.includes("/") ? repoSlug.split("/", 2) : [null, null];
|
|
16733
|
-
const repositoryId = (process.env.
|
|
16734
|
-
const installationId = (process.env.
|
|
17125
|
+
const repositoryId = (process.env.CONTRAST_REPO_ID || process.env.GITHUB_REPOSITORY_ID || "").trim();
|
|
17126
|
+
const installationId = (process.env.CONTRAST_INSTALLATION_ID || process.env.GITHUB_APP_INSTALLATION_ID || "").trim();
|
|
16735
17127
|
return {
|
|
16736
17128
|
kind: "github",
|
|
16737
17129
|
token,
|
|
@@ -16740,7 +17132,7 @@ function resolveGitHubActionsAuth() {
|
|
|
16740
17132
|
owner: owner || null,
|
|
16741
17133
|
repo: repo || null,
|
|
16742
17134
|
installationId: installationId || null,
|
|
16743
|
-
source:
|
|
17135
|
+
source: contrastRunnerToken ? "contrast-runner" : "github-actions"
|
|
16744
17136
|
};
|
|
16745
17137
|
}
|
|
16746
17138
|
function resolveCliAuth() {
|
|
@@ -16838,7 +17230,7 @@ var init_upload = __esm({
|
|
|
16838
17230
|
init_open_url2();
|
|
16839
17231
|
init_telemetry();
|
|
16840
17232
|
init_ws_bridge();
|
|
16841
|
-
REMOTE_DEFAULT_ORIGIN = process.env.SOOTSIM_UPLOAD_ORIGIN || "https://
|
|
17233
|
+
REMOTE_DEFAULT_ORIGIN = process.env.SOOTSIM_UPLOAD_ORIGIN || "https://contrast.dev";
|
|
16842
17234
|
REMOTE_DEFAULT_PUBLIC_PREVIEW_ORIGIN = process.env.SOOTSIM_PREVIEW_ORIGIN || "https://sootsim.com";
|
|
16843
17235
|
LOCAL_DEFAULT_ORIGIN = "http://localhost:3000";
|
|
16844
17236
|
LOCAL_UPLOAD_PROBE_TIMEOUT_MS = 2e3;
|
|
@@ -18869,147 +19261,8 @@ module.exports = __toCommonJS(registry_exports);
|
|
|
18869
19261
|
var fs10 = __toESM(require("fs"), 1);
|
|
18870
19262
|
var path10 = __toESM(require("path"), 1);
|
|
18871
19263
|
|
|
18872
|
-
// ../../scripts/lib/reap-browser.ts
|
|
18873
|
-
var import_node_child_process = require("node:child_process");
|
|
18874
|
-
function rootChromePid(b) {
|
|
18875
|
-
const w = b;
|
|
18876
|
-
if (w && typeof w.process === "function") {
|
|
18877
|
-
try {
|
|
18878
|
-
const p = w.process();
|
|
18879
|
-
if (p && typeof p.pid === "number" && p.pid > 0) return p.pid;
|
|
18880
|
-
} catch {
|
|
18881
|
-
}
|
|
18882
|
-
}
|
|
18883
|
-
if (w && typeof w.browser === "function") {
|
|
18884
|
-
try {
|
|
18885
|
-
const child = w.browser();
|
|
18886
|
-
if (child) return rootChromePid(child);
|
|
18887
|
-
} catch {
|
|
18888
|
-
}
|
|
18889
|
-
}
|
|
18890
|
-
return null;
|
|
18891
|
-
}
|
|
18892
|
-
function killTree(pid) {
|
|
18893
|
-
let kids = [];
|
|
18894
|
-
try {
|
|
18895
|
-
kids = (0, import_node_child_process.execSync)(`pgrep -P ${pid} || true`).toString().split("\n").filter(Boolean);
|
|
18896
|
-
} catch {
|
|
18897
|
-
}
|
|
18898
|
-
for (const k of kids) killTree(Number(k));
|
|
18899
|
-
try {
|
|
18900
|
-
process.kill(pid, "SIGKILL");
|
|
18901
|
-
} catch {
|
|
18902
|
-
}
|
|
18903
|
-
}
|
|
18904
|
-
var reapPids = /* @__PURE__ */ new Set();
|
|
18905
|
-
var installed = false;
|
|
18906
|
-
function installReaper() {
|
|
18907
|
-
if (installed) return;
|
|
18908
|
-
installed = true;
|
|
18909
|
-
const reap = () => {
|
|
18910
|
-
for (const pid of reapPids) killTree(pid);
|
|
18911
|
-
};
|
|
18912
|
-
process.on("SIGTERM", () => {
|
|
18913
|
-
reap();
|
|
18914
|
-
process.exit(0);
|
|
18915
|
-
});
|
|
18916
|
-
process.on("SIGINT", () => {
|
|
18917
|
-
reap();
|
|
18918
|
-
process.exit(0);
|
|
18919
|
-
});
|
|
18920
|
-
process.on("exit", reap);
|
|
18921
|
-
}
|
|
18922
|
-
async function launchReapedScoped(launch) {
|
|
18923
|
-
const browser = await launch();
|
|
18924
|
-
const root = rootChromePid(browser);
|
|
18925
|
-
const mine = /* @__PURE__ */ new Set();
|
|
18926
|
-
if (root != null) {
|
|
18927
|
-
mine.add(root);
|
|
18928
|
-
reapPids.add(root);
|
|
18929
|
-
installReaper();
|
|
18930
|
-
}
|
|
18931
|
-
const evented = browser;
|
|
18932
|
-
if (typeof evented.on === "function") {
|
|
18933
|
-
evented.on("disconnected", () => {
|
|
18934
|
-
for (const pid of mine) reapPids.delete(pid);
|
|
18935
|
-
});
|
|
18936
|
-
}
|
|
18937
|
-
const reapNow = () => {
|
|
18938
|
-
for (const pid of mine) {
|
|
18939
|
-
killTree(pid);
|
|
18940
|
-
reapPids.delete(pid);
|
|
18941
|
-
}
|
|
18942
|
-
mine.clear();
|
|
18943
|
-
};
|
|
18944
|
-
return { browser, reapNow };
|
|
18945
|
-
}
|
|
18946
|
-
async function launchReaped(launch) {
|
|
18947
|
-
const { browser } = await launchReapedScoped(launch);
|
|
18948
|
-
return browser;
|
|
18949
|
-
}
|
|
18950
|
-
var gpuChromeMissing = false;
|
|
18951
|
-
function gpuChromeArgs() {
|
|
18952
|
-
const angle = process.platform === "darwin" ? "metal" : process.platform === "linux" ? "vulkan" : "default";
|
|
18953
|
-
return [
|
|
18954
|
-
`--use-angle=${angle}`,
|
|
18955
|
-
"--enable-gpu",
|
|
18956
|
-
"--enable-gpu-rasterization",
|
|
18957
|
-
"--enable-zero-copy",
|
|
18958
|
-
"--ignore-gpu-blocklist"
|
|
18959
|
-
];
|
|
18960
|
-
}
|
|
18961
|
-
function gpuChromeLaunchOptions(opts = {}) {
|
|
18962
|
-
const callerArgs = Array.isArray(opts.args) ? opts.args : [];
|
|
18963
|
-
const callerIgnored = Array.isArray(opts.ignoreDefaultArgs) ? opts.ignoreDefaultArgs : [];
|
|
18964
|
-
return {
|
|
18965
|
-
...opts,
|
|
18966
|
-
// playwright's `chromium` channel is the full Google Chrome for Testing
|
|
18967
|
-
// app, not chromium_headless_shell. on macOS it has bundle id
|
|
18968
|
-
// com.google.chrome.for.testing, so automation cannot become the target of
|
|
18969
|
-
// Dock open/quit events intended for the user's com.google.Chrome browser.
|
|
18970
|
-
channel: "chromium",
|
|
18971
|
-
args: [...gpuChromeArgs(), ...callerArgs],
|
|
18972
|
-
ignoreDefaultArgs: [...callerIgnored, "--enable-unsafe-swiftshader"]
|
|
18973
|
-
};
|
|
18974
|
-
}
|
|
18975
|
-
function preferGpuChrome(launch, opts) {
|
|
18976
|
-
return async () => {
|
|
18977
|
-
const allowSoftwareFallback = process.env.CI === "true" || process.env.CI === "1" || process.env.GITHUB_ACTIONS === "true";
|
|
18978
|
-
if (!gpuChromeMissing) {
|
|
18979
|
-
try {
|
|
18980
|
-
const callerArgs = Array.isArray(opts.args) ? opts.args : [];
|
|
18981
|
-
if (!allowSoftwareFallback && callerArgs.some(
|
|
18982
|
-
(arg) => arg === "--enable-unsafe-swiftshader" || /^--use-angle=(?:swiftshader|swiftshader-webgl)$/i.test(String(arg))
|
|
18983
|
-
)) {
|
|
18984
|
-
throw new Error("[reap-browser] refused local SwiftShader launch arguments");
|
|
18985
|
-
}
|
|
18986
|
-
return await launch(gpuChromeLaunchOptions(opts));
|
|
18987
|
-
} catch (err) {
|
|
18988
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
18989
|
-
const missing = /not found at|not installed|Chromium distribution|Executable doesn't exist|No such file/i.test(
|
|
18990
|
-
msg
|
|
18991
|
-
);
|
|
18992
|
-
if (!missing) throw err;
|
|
18993
|
-
if (!allowSoftwareFallback) {
|
|
18994
|
-
throw new Error(
|
|
18995
|
-
"[reap-browser] Playwright Chrome for Testing is required for local GPU browser work; chromium_headless_shell fallback is disabled. Run `bunx playwright install chromium`.",
|
|
18996
|
-
{ cause: err }
|
|
18997
|
-
);
|
|
18998
|
-
}
|
|
18999
|
-
gpuChromeMissing = true;
|
|
19000
|
-
console.warn(
|
|
19001
|
-
"[reap-browser] CI Chrome for Testing not found, falling back to chromium_headless_shell software rendering."
|
|
19002
|
-
);
|
|
19003
|
-
}
|
|
19004
|
-
}
|
|
19005
|
-
return launch(opts);
|
|
19006
|
-
};
|
|
19007
|
-
}
|
|
19008
|
-
async function launchReapedChrome(launch, opts = {}) {
|
|
19009
|
-
return launchReaped(preferGpuChrome(launch, opts));
|
|
19010
|
-
}
|
|
19011
|
-
|
|
19012
19264
|
// src/skills/builtin/a11y-review.ts
|
|
19265
|
+
init_reap_browser();
|
|
19013
19266
|
var skill = {
|
|
19014
19267
|
name: "a11y-review",
|
|
19015
19268
|
description: "Check the app for accessibility issues",
|
|
@@ -19283,6 +19536,7 @@ var skill3 = {
|
|
|
19283
19536
|
};
|
|
19284
19537
|
|
|
19285
19538
|
// src/skills/builtin/perf-profile.ts
|
|
19539
|
+
init_reap_browser();
|
|
19286
19540
|
var skill4 = {
|
|
19287
19541
|
name: "perf-profile",
|
|
19288
19542
|
description: "Profile render performance of the app",
|
|
@@ -19350,6 +19604,7 @@ var skill4 = {
|
|
|
19350
19604
|
};
|
|
19351
19605
|
|
|
19352
19606
|
// src/skills/builtin/screenshot-all.ts
|
|
19607
|
+
init_reap_browser();
|
|
19353
19608
|
var skill5 = {
|
|
19354
19609
|
name: "screenshot-all",
|
|
19355
19610
|
description: "Capture screenshots of all screens in the app",
|
|
@@ -19392,6 +19647,7 @@ var skill5 = {
|
|
|
19392
19647
|
};
|
|
19393
19648
|
|
|
19394
19649
|
// src/skills/builtin/visual-diff.ts
|
|
19650
|
+
init_reap_browser();
|
|
19395
19651
|
var skill6 = {
|
|
19396
19652
|
name: "visual-diff",
|
|
19397
19653
|
description: "Compare current rendering against baseline screenshots",
|