@modeloslab/modelcode 0.1.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 +73 -0
- package/SPEC.md +127 -0
- package/agents/code-reviewer.md +49 -0
- package/agents/debugger.md +25 -0
- package/agents/explore.md +22 -0
- package/agents/general-purpose.md +25 -0
- package/agents/plan.md +28 -0
- package/agents/researcher.md +26 -0
- package/agents/security-auditor.md +44 -0
- package/dist/BrowserWebSocketTransport-e6g854ra.mjs +8 -0
- package/dist/LaunchOptions-d24f2e73.mjs +8 -0
- package/dist/NodeWebSocketTransport-s3fsfh3j.mjs +9 -0
- package/dist/bidi-fwqajnyx.mjs +17261 -0
- package/dist/cli.mjs +1669 -0
- package/dist/devtools-fkz8mzpk.mjs +83 -0
- package/dist/fileFromPath-s8scncrt.mjs +128 -0
- package/dist/helpers-667kxskd.mjs +17 -0
- package/dist/index-4706p1xh.mjs +3238 -0
- package/dist/index-gp8nzd9n.mjs +1561 -0
- package/dist/main-0r35eyef.mjs +16229 -0
- package/dist/main-2aqyq9g6.mjs +24239 -0
- package/dist/main-5vqwebnv.mjs +54 -0
- package/dist/main-7f2pnmhh.mjs +2901 -0
- package/dist/main-7jta7ark.mjs +57 -0
- package/dist/main-8y3fe7c3.mjs +48 -0
- package/dist/main-9w13grbs.mjs +41 -0
- package/dist/main-d71btkt1.mjs +2478 -0
- package/dist/main-h8e68gyt.mjs +2819 -0
- package/dist/main-p2xnn95s.mjs +2240 -0
- package/dist/main-qfprs50h.mjs +1629 -0
- package/dist/main-tqg5vhra.mjs +19 -0
- package/dist/puppeteer-core-qdv3v3fq.mjs +1486 -0
- package/dist/tui-0r2q70wm.mjs +23768 -0
- package/package.json +66 -0
- package/skills/commit/SKILL.md +34 -0
- package/skills/debug/SKILL.md +44 -0
- package/skills/docker/SKILL.md +18 -0
- package/skills/init/SKILL.md +36 -0
- package/skills/nextjs-app-router/SKILL.md +16 -0
- package/skills/nextjs-data-fetching/SKILL.md +16 -0
- package/skills/nextjs-env-config/SKILL.md +18 -0
- package/skills/nextjs-metadata-seo/SKILL.md +17 -0
- package/skills/nextjs-middleware/SKILL.md +18 -0
- package/skills/nextjs-performance/SKILL.md +17 -0
- package/skills/nextjs-route-handler/SKILL.md +18 -0
- package/skills/nextjs-server-actions/SKILL.md +17 -0
- package/skills/nextjs-server-components/SKILL.md +18 -0
- package/skills/power-ui/SKILL.md +40 -0
- package/skills/pr/SKILL.md +38 -0
- package/skills/refactor/SKILL.md +40 -0
- package/skills/remember/SKILL.md +39 -0
- package/skills/review/SKILL.md +22 -0
- package/skills/security-review/SKILL.md +21 -0
- package/skills/simplify/SKILL.md +47 -0
- package/skills/skill-create/SKILL.md +37 -0
- package/skills/test/SKILL.md +34 -0
- package/skills/vercel-deploy/SKILL.md +16 -0
|
@@ -0,0 +1,2478 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require
|
|
3
|
+
} from "./main-8y3fe7c3.mjs";
|
|
4
|
+
|
|
5
|
+
// node_modules/@puppeteer/browsers/lib/launch.js
|
|
6
|
+
import childProcess from "node:child_process";
|
|
7
|
+
import { EventEmitter } from "node:events";
|
|
8
|
+
import { accessSync } from "node:fs";
|
|
9
|
+
import os4 from "node:os";
|
|
10
|
+
import readline from "node:readline";
|
|
11
|
+
|
|
12
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chrome-headless-shell.js
|
|
13
|
+
import path2 from "node:path";
|
|
14
|
+
|
|
15
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/types.js
|
|
16
|
+
var Browser;
|
|
17
|
+
(function(Browser2) {
|
|
18
|
+
Browser2["CHROME"] = "chrome";
|
|
19
|
+
Browser2["CHROMEHEADLESSSHELL"] = "chrome-headless-shell";
|
|
20
|
+
Browser2["CHROMIUM"] = "chromium";
|
|
21
|
+
Browser2["FIREFOX"] = "firefox";
|
|
22
|
+
Browser2["CHROMEDRIVER"] = "chromedriver";
|
|
23
|
+
})(Browser || (Browser = {}));
|
|
24
|
+
var BrowserPlatform;
|
|
25
|
+
(function(BrowserPlatform2) {
|
|
26
|
+
BrowserPlatform2["LINUX"] = "linux";
|
|
27
|
+
BrowserPlatform2["LINUX_ARM"] = "linux_arm";
|
|
28
|
+
BrowserPlatform2["MAC"] = "mac";
|
|
29
|
+
BrowserPlatform2["MAC_ARM"] = "mac_arm";
|
|
30
|
+
BrowserPlatform2["WIN32"] = "win32";
|
|
31
|
+
BrowserPlatform2["WIN64"] = "win64";
|
|
32
|
+
})(BrowserPlatform || (BrowserPlatform = {}));
|
|
33
|
+
var BrowserTag;
|
|
34
|
+
(function(BrowserTag2) {
|
|
35
|
+
BrowserTag2["CANARY"] = "canary";
|
|
36
|
+
BrowserTag2["NIGHTLY"] = "nightly";
|
|
37
|
+
BrowserTag2["BETA"] = "beta";
|
|
38
|
+
BrowserTag2["DEV"] = "dev";
|
|
39
|
+
BrowserTag2["DEVEDITION"] = "devedition";
|
|
40
|
+
BrowserTag2["STABLE"] = "stable";
|
|
41
|
+
BrowserTag2["ESR"] = "esr";
|
|
42
|
+
BrowserTag2["LATEST"] = "latest";
|
|
43
|
+
})(BrowserTag || (BrowserTag = {}));
|
|
44
|
+
var ChromeReleaseChannel;
|
|
45
|
+
(function(ChromeReleaseChannel2) {
|
|
46
|
+
ChromeReleaseChannel2["STABLE"] = "stable";
|
|
47
|
+
ChromeReleaseChannel2["DEV"] = "dev";
|
|
48
|
+
ChromeReleaseChannel2["CANARY"] = "canary";
|
|
49
|
+
ChromeReleaseChannel2["BETA"] = "beta";
|
|
50
|
+
})(ChromeReleaseChannel || (ChromeReleaseChannel = {}));
|
|
51
|
+
|
|
52
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chrome.js
|
|
53
|
+
import { execSync } from "node:child_process";
|
|
54
|
+
import os from "node:os";
|
|
55
|
+
import path from "node:path";
|
|
56
|
+
|
|
57
|
+
// node_modules/@puppeteer/browsers/lib/httpUtil.js
|
|
58
|
+
import { createWriteStream } from "node:fs";
|
|
59
|
+
import * as http from "node:http";
|
|
60
|
+
import * as https from "node:https";
|
|
61
|
+
import { URL as URL2, urlToHttpOptions } from "node:url";
|
|
62
|
+
async function headHttpRequest(url) {
|
|
63
|
+
return await new Promise((resolve) => {
|
|
64
|
+
httpRequest(url, "HEAD", (response) => {
|
|
65
|
+
response.resume();
|
|
66
|
+
resolve(response.statusCode === 200);
|
|
67
|
+
}, false).then((request3) => {
|
|
68
|
+
request3.on("error", () => {
|
|
69
|
+
resolve(false);
|
|
70
|
+
});
|
|
71
|
+
}).catch(() => {
|
|
72
|
+
resolve(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async function httpRequest(url, method, response, keepAlive = true) {
|
|
77
|
+
let agent;
|
|
78
|
+
try {
|
|
79
|
+
const { ProxyAgent } = await import("proxy-agent");
|
|
80
|
+
agent = new ProxyAgent;
|
|
81
|
+
} catch {}
|
|
82
|
+
const options = {
|
|
83
|
+
protocol: url.protocol,
|
|
84
|
+
hostname: url.hostname,
|
|
85
|
+
port: url.port,
|
|
86
|
+
path: url.pathname + url.search,
|
|
87
|
+
method,
|
|
88
|
+
headers: keepAlive ? { Connection: "keep-alive" } : undefined,
|
|
89
|
+
auth: urlToHttpOptions(url).auth,
|
|
90
|
+
agent
|
|
91
|
+
};
|
|
92
|
+
const requestCallback = (res) => {
|
|
93
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
94
|
+
httpRequest(new URL2(res.headers.location), method, response);
|
|
95
|
+
res.resume();
|
|
96
|
+
} else {
|
|
97
|
+
response(res);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const request3 = options.protocol === "https:" ? https.request(options, requestCallback) : http.request(options, requestCallback);
|
|
101
|
+
request3.end();
|
|
102
|
+
return request3;
|
|
103
|
+
}
|
|
104
|
+
function downloadFile(url, destinationPath, progressCallback) {
|
|
105
|
+
return new Promise(async (resolve, reject) => {
|
|
106
|
+
let downloadedBytes = 0;
|
|
107
|
+
let totalBytes = 0;
|
|
108
|
+
function onData(chunk) {
|
|
109
|
+
downloadedBytes += chunk.length;
|
|
110
|
+
progressCallback(downloadedBytes, totalBytes);
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const request3 = await httpRequest(url, "GET", (response) => {
|
|
114
|
+
if (response.statusCode !== 200) {
|
|
115
|
+
const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
|
|
116
|
+
response.resume();
|
|
117
|
+
reject(error);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const file = createWriteStream(destinationPath);
|
|
121
|
+
file.on("close", () => {
|
|
122
|
+
return resolve();
|
|
123
|
+
});
|
|
124
|
+
file.on("error", (error) => {
|
|
125
|
+
return reject(error);
|
|
126
|
+
});
|
|
127
|
+
response.pipe(file);
|
|
128
|
+
totalBytes = parseInt(response.headers["content-length"], 10);
|
|
129
|
+
if (progressCallback) {
|
|
130
|
+
response.on("data", onData);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
request3.on("error", (error) => {
|
|
134
|
+
return reject(error);
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
reject(error);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async function getJSON(url) {
|
|
142
|
+
const text = await getText(url);
|
|
143
|
+
try {
|
|
144
|
+
return JSON.parse(text);
|
|
145
|
+
} catch {
|
|
146
|
+
throw new Error("Could not parse JSON from " + url.toString());
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function getText(url) {
|
|
150
|
+
return new Promise(async (resolve, reject) => {
|
|
151
|
+
try {
|
|
152
|
+
const request3 = await httpRequest(url, "GET", (response) => {
|
|
153
|
+
let data = "";
|
|
154
|
+
if (response.statusCode && response.statusCode >= 400) {
|
|
155
|
+
return reject(new Error(`Got status code ${response.statusCode}`));
|
|
156
|
+
}
|
|
157
|
+
response.on("data", (chunk) => {
|
|
158
|
+
data += chunk;
|
|
159
|
+
});
|
|
160
|
+
response.on("end", () => {
|
|
161
|
+
try {
|
|
162
|
+
return resolve(String(data));
|
|
163
|
+
} catch {
|
|
164
|
+
return reject(new Error(`Failed to read text response from ${url}`));
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}, false);
|
|
168
|
+
request3.on("error", (err) => {
|
|
169
|
+
reject(err);
|
|
170
|
+
});
|
|
171
|
+
} catch (err) {
|
|
172
|
+
reject(err);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chrome.js
|
|
178
|
+
function folder(platform) {
|
|
179
|
+
switch (platform) {
|
|
180
|
+
case BrowserPlatform.LINUX_ARM:
|
|
181
|
+
case BrowserPlatform.LINUX:
|
|
182
|
+
return "linux64";
|
|
183
|
+
case BrowserPlatform.MAC_ARM:
|
|
184
|
+
return "mac-arm64";
|
|
185
|
+
case BrowserPlatform.MAC:
|
|
186
|
+
return "mac-x64";
|
|
187
|
+
case BrowserPlatform.WIN32:
|
|
188
|
+
return "win32";
|
|
189
|
+
case BrowserPlatform.WIN64:
|
|
190
|
+
return "win64";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function resolveDownloadUrl(platform, buildId, baseUrl = "https://storage.googleapis.com/chrome-for-testing-public") {
|
|
194
|
+
return `${baseUrl}/${resolveDownloadPath(platform, buildId).join("/")}`;
|
|
195
|
+
}
|
|
196
|
+
function resolveDownloadPath(platform, buildId) {
|
|
197
|
+
return [buildId, folder(platform), `chrome-${folder(platform)}.zip`];
|
|
198
|
+
}
|
|
199
|
+
function relativeExecutablePath(platform, _buildId) {
|
|
200
|
+
switch (platform) {
|
|
201
|
+
case BrowserPlatform.MAC:
|
|
202
|
+
case BrowserPlatform.MAC_ARM:
|
|
203
|
+
return path.join("chrome-" + folder(platform), "Google Chrome for Testing.app", "Contents", "MacOS", "Google Chrome for Testing");
|
|
204
|
+
case BrowserPlatform.LINUX_ARM:
|
|
205
|
+
case BrowserPlatform.LINUX:
|
|
206
|
+
return path.join("chrome-linux64", "chrome");
|
|
207
|
+
case BrowserPlatform.WIN32:
|
|
208
|
+
case BrowserPlatform.WIN64:
|
|
209
|
+
return path.join("chrome-" + folder(platform), "chrome.exe");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
var baseVersionUrl = "https://googlechromelabs.github.io/chrome-for-testing";
|
|
213
|
+
async function getLastKnownGoodReleaseForChannel(channel) {
|
|
214
|
+
const data = await getJSON(new URL(`${baseVersionUrl}/last-known-good-versions.json`));
|
|
215
|
+
for (const channel2 of Object.keys(data.channels)) {
|
|
216
|
+
data.channels[channel2.toLowerCase()] = data.channels[channel2];
|
|
217
|
+
delete data.channels[channel2];
|
|
218
|
+
}
|
|
219
|
+
return data.channels[channel];
|
|
220
|
+
}
|
|
221
|
+
async function getLastKnownGoodReleaseForMilestone(milestone) {
|
|
222
|
+
const data = await getJSON(new URL(`${baseVersionUrl}/latest-versions-per-milestone.json`));
|
|
223
|
+
return data.milestones[milestone];
|
|
224
|
+
}
|
|
225
|
+
async function getLastKnownGoodReleaseForBuild(buildPrefix) {
|
|
226
|
+
const data = await getJSON(new URL(`${baseVersionUrl}/latest-patch-versions-per-build.json`));
|
|
227
|
+
return data.builds[buildPrefix];
|
|
228
|
+
}
|
|
229
|
+
async function resolveBuildId(channel) {
|
|
230
|
+
if (Object.values(ChromeReleaseChannel).includes(channel)) {
|
|
231
|
+
return (await getLastKnownGoodReleaseForChannel(channel)).version;
|
|
232
|
+
}
|
|
233
|
+
if (channel.match(/^\d+$/)) {
|
|
234
|
+
return (await getLastKnownGoodReleaseForMilestone(channel))?.version;
|
|
235
|
+
}
|
|
236
|
+
if (channel.match(/^\d+\.\d+\.\d+$/)) {
|
|
237
|
+
return (await getLastKnownGoodReleaseForBuild(channel))?.version;
|
|
238
|
+
}
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
var WINDOWS_ENV_PARAM_NAMES = [
|
|
242
|
+
"PROGRAMFILES",
|
|
243
|
+
"ProgramW6432",
|
|
244
|
+
"ProgramFiles(x86)",
|
|
245
|
+
"LOCALAPPDATA"
|
|
246
|
+
];
|
|
247
|
+
function getChromeWindowsLocation(channel, locationsPrefixes) {
|
|
248
|
+
if (locationsPrefixes.size === 0) {
|
|
249
|
+
throw new Error("Non of the common Windows Env variables were set");
|
|
250
|
+
}
|
|
251
|
+
let suffix;
|
|
252
|
+
switch (channel) {
|
|
253
|
+
case ChromeReleaseChannel.STABLE:
|
|
254
|
+
suffix = "Google\\Chrome\\Application\\chrome.exe";
|
|
255
|
+
break;
|
|
256
|
+
case ChromeReleaseChannel.BETA:
|
|
257
|
+
suffix = "Google\\Chrome Beta\\Application\\chrome.exe";
|
|
258
|
+
break;
|
|
259
|
+
case ChromeReleaseChannel.CANARY:
|
|
260
|
+
suffix = "Google\\Chrome SxS\\Application\\chrome.exe";
|
|
261
|
+
break;
|
|
262
|
+
case ChromeReleaseChannel.DEV:
|
|
263
|
+
suffix = "Google\\Chrome Dev\\Application\\chrome.exe";
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
return [...locationsPrefixes.values()].map((l) => {
|
|
267
|
+
return path.win32.join(l, suffix);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function getWslVariable(variable) {
|
|
271
|
+
try {
|
|
272
|
+
const result = execSync(`cmd.exe /c echo %${variable.toLocaleUpperCase()}%`, {
|
|
273
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
274
|
+
encoding: "utf-8"
|
|
275
|
+
}).trim();
|
|
276
|
+
if (result) {
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
} catch {}
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
function getWslLocation(channel) {
|
|
283
|
+
const wslVersion = execSync("wslinfo --version", {
|
|
284
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
285
|
+
encoding: "utf-8"
|
|
286
|
+
}).trim();
|
|
287
|
+
if (!wslVersion) {
|
|
288
|
+
throw new Error("Not in WSL or unsupported version of WSL.");
|
|
289
|
+
}
|
|
290
|
+
const wslPrefixes = new Set;
|
|
291
|
+
for (const name of WINDOWS_ENV_PARAM_NAMES) {
|
|
292
|
+
const wslPrefix = getWslVariable(name);
|
|
293
|
+
if (wslPrefix) {
|
|
294
|
+
wslPrefixes.add(wslPrefix);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const windowsPath = getChromeWindowsLocation(channel, wslPrefixes);
|
|
298
|
+
return windowsPath.map((path2) => {
|
|
299
|
+
return execSync(`wslpath "${path2}"`).toString().trim();
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
function getChromeLinuxOrWslLocation(channel) {
|
|
303
|
+
const locations = [];
|
|
304
|
+
switch (channel) {
|
|
305
|
+
case ChromeReleaseChannel.STABLE:
|
|
306
|
+
locations.push("/opt/google/chrome/chrome");
|
|
307
|
+
break;
|
|
308
|
+
case ChromeReleaseChannel.BETA:
|
|
309
|
+
locations.push("/opt/google/chrome-beta/chrome");
|
|
310
|
+
break;
|
|
311
|
+
case ChromeReleaseChannel.CANARY:
|
|
312
|
+
locations.push("/opt/google/chrome-canary/chrome");
|
|
313
|
+
break;
|
|
314
|
+
case ChromeReleaseChannel.DEV:
|
|
315
|
+
locations.push("/opt/google/chrome-unstable/chrome");
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const wslPath = getWslLocation(channel);
|
|
320
|
+
if (wslPath) {
|
|
321
|
+
locations.push(...wslPath);
|
|
322
|
+
}
|
|
323
|
+
} catch {}
|
|
324
|
+
return locations;
|
|
325
|
+
}
|
|
326
|
+
function resolveSystemExecutablePaths(platform, channel) {
|
|
327
|
+
switch (platform) {
|
|
328
|
+
case BrowserPlatform.WIN64:
|
|
329
|
+
case BrowserPlatform.WIN32:
|
|
330
|
+
const prefixLocation = new Set(WINDOWS_ENV_PARAM_NAMES.map((name) => {
|
|
331
|
+
return process.env[name];
|
|
332
|
+
}).filter((l) => {
|
|
333
|
+
return !!l;
|
|
334
|
+
}));
|
|
335
|
+
prefixLocation.add("C:\\Program Files");
|
|
336
|
+
prefixLocation.add("C:\\Program Files (x86)");
|
|
337
|
+
prefixLocation.add("D:\\Program Files");
|
|
338
|
+
prefixLocation.add("D:\\Program Files (x86)");
|
|
339
|
+
return getChromeWindowsLocation(channel, prefixLocation);
|
|
340
|
+
case BrowserPlatform.MAC_ARM:
|
|
341
|
+
case BrowserPlatform.MAC:
|
|
342
|
+
switch (channel) {
|
|
343
|
+
case ChromeReleaseChannel.STABLE:
|
|
344
|
+
return [
|
|
345
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
346
|
+
];
|
|
347
|
+
case ChromeReleaseChannel.BETA:
|
|
348
|
+
return [
|
|
349
|
+
"/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
|
|
350
|
+
];
|
|
351
|
+
case ChromeReleaseChannel.CANARY:
|
|
352
|
+
return [
|
|
353
|
+
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
|
|
354
|
+
];
|
|
355
|
+
case ChromeReleaseChannel.DEV:
|
|
356
|
+
return [
|
|
357
|
+
"/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
|
|
358
|
+
];
|
|
359
|
+
}
|
|
360
|
+
case BrowserPlatform.LINUX_ARM:
|
|
361
|
+
case BrowserPlatform.LINUX:
|
|
362
|
+
return getChromeLinuxOrWslLocation(channel);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function resolveDefaultUserDataDir(platform, channel) {
|
|
366
|
+
switch (platform) {
|
|
367
|
+
case BrowserPlatform.WIN64:
|
|
368
|
+
case BrowserPlatform.WIN32:
|
|
369
|
+
switch (channel) {
|
|
370
|
+
case ChromeReleaseChannel.STABLE:
|
|
371
|
+
return path.join(getLocalAppDataWin(), "Google", "Chrome", "User Data");
|
|
372
|
+
case ChromeReleaseChannel.BETA:
|
|
373
|
+
return path.join(getLocalAppDataWin(), "Google", "Chrome Beta", "User Data");
|
|
374
|
+
case ChromeReleaseChannel.CANARY:
|
|
375
|
+
return path.join(getLocalAppDataWin(), "Google", "Chrome SxS", "User Data");
|
|
376
|
+
case ChromeReleaseChannel.DEV:
|
|
377
|
+
return path.join(getLocalAppDataWin(), "Google", "Chrome Dev", "User Data");
|
|
378
|
+
}
|
|
379
|
+
case BrowserPlatform.MAC_ARM:
|
|
380
|
+
case BrowserPlatform.MAC:
|
|
381
|
+
switch (channel) {
|
|
382
|
+
case ChromeReleaseChannel.STABLE:
|
|
383
|
+
return path.join(getBaseUserDataDirPathMac(), "Chrome");
|
|
384
|
+
case ChromeReleaseChannel.BETA:
|
|
385
|
+
return path.join(getBaseUserDataDirPathMac(), "Chrome Beta");
|
|
386
|
+
case ChromeReleaseChannel.DEV:
|
|
387
|
+
return path.join(getBaseUserDataDirPathMac(), "Chrome Dev");
|
|
388
|
+
case ChromeReleaseChannel.CANARY:
|
|
389
|
+
return path.join(getBaseUserDataDirPathMac(), "Chrome Canary");
|
|
390
|
+
}
|
|
391
|
+
case BrowserPlatform.LINUX_ARM:
|
|
392
|
+
case BrowserPlatform.LINUX:
|
|
393
|
+
switch (channel) {
|
|
394
|
+
case ChromeReleaseChannel.STABLE:
|
|
395
|
+
return path.join(getConfigHomeLinux(), "google-chrome");
|
|
396
|
+
case ChromeReleaseChannel.BETA:
|
|
397
|
+
return path.join(getConfigHomeLinux(), "google-chrome-beta");
|
|
398
|
+
case ChromeReleaseChannel.CANARY:
|
|
399
|
+
return path.join(getConfigHomeLinux(), "google-chrome-canary");
|
|
400
|
+
case ChromeReleaseChannel.DEV:
|
|
401
|
+
return path.join(getConfigHomeLinux(), "google-chrome-unstable");
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function getLocalAppDataWin() {
|
|
406
|
+
return process.env["LOCALAPPDATA"] || path.join(os.homedir(), "AppData", "Local");
|
|
407
|
+
}
|
|
408
|
+
function getConfigHomeLinux() {
|
|
409
|
+
return process.env["CHROME_CONFIG_HOME"] || process.env["XDG_CONFIG_HOME"] || path.join(os.homedir(), ".config");
|
|
410
|
+
}
|
|
411
|
+
function getBaseUserDataDirPathMac() {
|
|
412
|
+
return path.join(os.homedir(), "Library", "Application Support", "Google");
|
|
413
|
+
}
|
|
414
|
+
function compareVersions(a, b) {
|
|
415
|
+
const cleanA = a.trim();
|
|
416
|
+
const cleanB = b.trim();
|
|
417
|
+
const versionRegex = /^\d+(?:\.\d+){0,3}$/;
|
|
418
|
+
if (!versionRegex.test(cleanA)) {
|
|
419
|
+
throw new Error(`Version ${a} is not a valid Chrome version`);
|
|
420
|
+
}
|
|
421
|
+
if (!versionRegex.test(cleanB)) {
|
|
422
|
+
throw new Error(`Version ${b} is not a valid Chrome version`);
|
|
423
|
+
}
|
|
424
|
+
const aParts = cleanA.split(".").map(Number);
|
|
425
|
+
const bParts = cleanB.split(".").map(Number);
|
|
426
|
+
for (let i = 0;i < 4; i++) {
|
|
427
|
+
const aPart = aParts[i] ?? 0;
|
|
428
|
+
const bPart = bParts[i] ?? 0;
|
|
429
|
+
if (aPart > bPart) {
|
|
430
|
+
return 1;
|
|
431
|
+
}
|
|
432
|
+
if (aPart < bPart) {
|
|
433
|
+
return -1;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return 0;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chrome-headless-shell.js
|
|
440
|
+
function folder2(platform) {
|
|
441
|
+
switch (platform) {
|
|
442
|
+
case BrowserPlatform.LINUX_ARM:
|
|
443
|
+
case BrowserPlatform.LINUX:
|
|
444
|
+
return "linux64";
|
|
445
|
+
case BrowserPlatform.MAC_ARM:
|
|
446
|
+
return "mac-arm64";
|
|
447
|
+
case BrowserPlatform.MAC:
|
|
448
|
+
return "mac-x64";
|
|
449
|
+
case BrowserPlatform.WIN32:
|
|
450
|
+
return "win32";
|
|
451
|
+
case BrowserPlatform.WIN64:
|
|
452
|
+
return "win64";
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function resolveDownloadUrl2(platform, buildId, baseUrl = "https://storage.googleapis.com/chrome-for-testing-public") {
|
|
456
|
+
return `${baseUrl}/${resolveDownloadPath2(platform, buildId).join("/")}`;
|
|
457
|
+
}
|
|
458
|
+
function resolveDownloadPath2(platform, buildId) {
|
|
459
|
+
return [
|
|
460
|
+
buildId,
|
|
461
|
+
folder2(platform),
|
|
462
|
+
`chrome-headless-shell-${folder2(platform)}.zip`
|
|
463
|
+
];
|
|
464
|
+
}
|
|
465
|
+
function relativeExecutablePath2(platform, _buildId) {
|
|
466
|
+
switch (platform) {
|
|
467
|
+
case BrowserPlatform.MAC:
|
|
468
|
+
case BrowserPlatform.MAC_ARM:
|
|
469
|
+
return path2.join("chrome-headless-shell-" + folder2(platform), "chrome-headless-shell");
|
|
470
|
+
case BrowserPlatform.LINUX_ARM:
|
|
471
|
+
case BrowserPlatform.LINUX:
|
|
472
|
+
return path2.join("chrome-headless-shell-linux64", "chrome-headless-shell");
|
|
473
|
+
case BrowserPlatform.WIN32:
|
|
474
|
+
case BrowserPlatform.WIN64:
|
|
475
|
+
return path2.join("chrome-headless-shell-" + folder2(platform), "chrome-headless-shell.exe");
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chromedriver.js
|
|
480
|
+
import path3 from "node:path";
|
|
481
|
+
function folder3(platform) {
|
|
482
|
+
switch (platform) {
|
|
483
|
+
case BrowserPlatform.LINUX_ARM:
|
|
484
|
+
case BrowserPlatform.LINUX:
|
|
485
|
+
return "linux64";
|
|
486
|
+
case BrowserPlatform.MAC_ARM:
|
|
487
|
+
return "mac-arm64";
|
|
488
|
+
case BrowserPlatform.MAC:
|
|
489
|
+
return "mac-x64";
|
|
490
|
+
case BrowserPlatform.WIN32:
|
|
491
|
+
return "win32";
|
|
492
|
+
case BrowserPlatform.WIN64:
|
|
493
|
+
return "win64";
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function resolveDownloadUrl3(platform, buildId, baseUrl = "https://storage.googleapis.com/chrome-for-testing-public") {
|
|
497
|
+
return `${baseUrl}/${resolveDownloadPath3(platform, buildId).join("/")}`;
|
|
498
|
+
}
|
|
499
|
+
function resolveDownloadPath3(platform, buildId) {
|
|
500
|
+
return [buildId, folder3(platform), `chromedriver-${folder3(platform)}.zip`];
|
|
501
|
+
}
|
|
502
|
+
function relativeExecutablePath3(platform, _buildId) {
|
|
503
|
+
switch (platform) {
|
|
504
|
+
case BrowserPlatform.MAC:
|
|
505
|
+
case BrowserPlatform.MAC_ARM:
|
|
506
|
+
return path3.join("chromedriver-" + folder3(platform), "chromedriver");
|
|
507
|
+
case BrowserPlatform.LINUX_ARM:
|
|
508
|
+
case BrowserPlatform.LINUX:
|
|
509
|
+
return path3.join("chromedriver-linux64", "chromedriver");
|
|
510
|
+
case BrowserPlatform.WIN32:
|
|
511
|
+
case BrowserPlatform.WIN64:
|
|
512
|
+
return path3.join("chromedriver-" + folder3(platform), "chromedriver.exe");
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/chromium.js
|
|
517
|
+
import path4 from "node:path";
|
|
518
|
+
function archive(platform, buildId) {
|
|
519
|
+
switch (platform) {
|
|
520
|
+
case BrowserPlatform.LINUX_ARM:
|
|
521
|
+
case BrowserPlatform.LINUX:
|
|
522
|
+
return "chrome-linux";
|
|
523
|
+
case BrowserPlatform.MAC_ARM:
|
|
524
|
+
case BrowserPlatform.MAC:
|
|
525
|
+
return "chrome-mac";
|
|
526
|
+
case BrowserPlatform.WIN32:
|
|
527
|
+
case BrowserPlatform.WIN64:
|
|
528
|
+
return parseInt(buildId, 10) > 591479 ? "chrome-win" : "chrome-win32";
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function folder4(platform) {
|
|
532
|
+
switch (platform) {
|
|
533
|
+
case BrowserPlatform.LINUX_ARM:
|
|
534
|
+
case BrowserPlatform.LINUX:
|
|
535
|
+
return "Linux_x64";
|
|
536
|
+
case BrowserPlatform.MAC_ARM:
|
|
537
|
+
return "Mac_Arm";
|
|
538
|
+
case BrowserPlatform.MAC:
|
|
539
|
+
return "Mac";
|
|
540
|
+
case BrowserPlatform.WIN32:
|
|
541
|
+
return "Win";
|
|
542
|
+
case BrowserPlatform.WIN64:
|
|
543
|
+
return "Win_x64";
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function resolveDownloadUrl4(platform, buildId, baseUrl = "https://storage.googleapis.com/chromium-browser-snapshots") {
|
|
547
|
+
return `${baseUrl}/${resolveDownloadPath4(platform, buildId).join("/")}`;
|
|
548
|
+
}
|
|
549
|
+
function resolveDownloadPath4(platform, buildId) {
|
|
550
|
+
return [folder4(platform), buildId, `${archive(platform, buildId)}.zip`];
|
|
551
|
+
}
|
|
552
|
+
function relativeExecutablePath4(platform, _buildId) {
|
|
553
|
+
switch (platform) {
|
|
554
|
+
case BrowserPlatform.MAC:
|
|
555
|
+
case BrowserPlatform.MAC_ARM:
|
|
556
|
+
return path4.join("chrome-mac", "Chromium.app", "Contents", "MacOS", "Chromium");
|
|
557
|
+
case BrowserPlatform.LINUX_ARM:
|
|
558
|
+
case BrowserPlatform.LINUX:
|
|
559
|
+
return path4.join("chrome-linux", "chrome");
|
|
560
|
+
case BrowserPlatform.WIN32:
|
|
561
|
+
case BrowserPlatform.WIN64:
|
|
562
|
+
return path4.join("chrome-win", "chrome.exe");
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
async function resolveBuildId2(platform) {
|
|
566
|
+
return await getText(new URL(`https://storage.googleapis.com/chromium-browser-snapshots/${folder4(platform)}/LAST_CHANGE`));
|
|
567
|
+
}
|
|
568
|
+
function compareVersions2(a, b) {
|
|
569
|
+
return Number(a) - Number(b);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/firefox.js
|
|
573
|
+
import fs from "node:fs";
|
|
574
|
+
import path5 from "node:path";
|
|
575
|
+
function getFormat(buildId) {
|
|
576
|
+
const majorVersion = Number(buildId.split(".").shift());
|
|
577
|
+
return majorVersion >= 135 ? "xz" : "bz2";
|
|
578
|
+
}
|
|
579
|
+
function archiveNightly(platform, buildId) {
|
|
580
|
+
switch (platform) {
|
|
581
|
+
case BrowserPlatform.LINUX:
|
|
582
|
+
return `firefox-${buildId}.en-US.linux-x86_64.tar.${getFormat(buildId)}`;
|
|
583
|
+
case BrowserPlatform.LINUX_ARM:
|
|
584
|
+
return `firefox-${buildId}.en-US.linux-aarch64.tar.${getFormat(buildId)}`;
|
|
585
|
+
case BrowserPlatform.MAC_ARM:
|
|
586
|
+
case BrowserPlatform.MAC:
|
|
587
|
+
return `firefox-${buildId}.en-US.mac.dmg`;
|
|
588
|
+
case BrowserPlatform.WIN32:
|
|
589
|
+
case BrowserPlatform.WIN64:
|
|
590
|
+
return `firefox-${buildId}.en-US.${platform}.zip`;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function archive2(platform, buildId) {
|
|
594
|
+
switch (platform) {
|
|
595
|
+
case BrowserPlatform.LINUX_ARM:
|
|
596
|
+
case BrowserPlatform.LINUX:
|
|
597
|
+
return `firefox-${buildId}.tar.${getFormat(buildId)}`;
|
|
598
|
+
case BrowserPlatform.MAC_ARM:
|
|
599
|
+
case BrowserPlatform.MAC:
|
|
600
|
+
return `Firefox ${buildId}.dmg`;
|
|
601
|
+
case BrowserPlatform.WIN32:
|
|
602
|
+
case BrowserPlatform.WIN64:
|
|
603
|
+
return `Firefox Setup ${buildId}.exe`;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
function platformName(platform) {
|
|
607
|
+
switch (platform) {
|
|
608
|
+
case BrowserPlatform.LINUX:
|
|
609
|
+
return `linux-x86_64`;
|
|
610
|
+
case BrowserPlatform.LINUX_ARM:
|
|
611
|
+
return `linux-aarch64`;
|
|
612
|
+
case BrowserPlatform.MAC_ARM:
|
|
613
|
+
case BrowserPlatform.MAC:
|
|
614
|
+
return `mac`;
|
|
615
|
+
case BrowserPlatform.WIN32:
|
|
616
|
+
case BrowserPlatform.WIN64:
|
|
617
|
+
return platform;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function parseBuildId(buildId) {
|
|
621
|
+
for (const value of Object.values(FirefoxChannel)) {
|
|
622
|
+
if (buildId.startsWith(value + "_")) {
|
|
623
|
+
buildId = buildId.substring(value.length + 1);
|
|
624
|
+
return [value, buildId];
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return [FirefoxChannel.NIGHTLY, buildId];
|
|
628
|
+
}
|
|
629
|
+
function resolveDownloadUrl5(platform, buildId, baseUrl) {
|
|
630
|
+
const [channel] = parseBuildId(buildId);
|
|
631
|
+
switch (channel) {
|
|
632
|
+
case FirefoxChannel.NIGHTLY:
|
|
633
|
+
baseUrl ??= "https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central";
|
|
634
|
+
break;
|
|
635
|
+
case FirefoxChannel.DEVEDITION:
|
|
636
|
+
baseUrl ??= "https://archive.mozilla.org/pub/devedition/releases";
|
|
637
|
+
break;
|
|
638
|
+
case FirefoxChannel.BETA:
|
|
639
|
+
case FirefoxChannel.STABLE:
|
|
640
|
+
case FirefoxChannel.ESR:
|
|
641
|
+
baseUrl ??= "https://archive.mozilla.org/pub/firefox/releases";
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
return `${baseUrl}/${resolveDownloadPath5(platform, buildId).join("/")}`;
|
|
645
|
+
}
|
|
646
|
+
function resolveDownloadPath5(platform, buildId) {
|
|
647
|
+
const [channel, resolvedBuildId] = parseBuildId(buildId);
|
|
648
|
+
switch (channel) {
|
|
649
|
+
case FirefoxChannel.NIGHTLY:
|
|
650
|
+
return [archiveNightly(platform, resolvedBuildId)];
|
|
651
|
+
case FirefoxChannel.DEVEDITION:
|
|
652
|
+
case FirefoxChannel.BETA:
|
|
653
|
+
case FirefoxChannel.STABLE:
|
|
654
|
+
case FirefoxChannel.ESR:
|
|
655
|
+
return [
|
|
656
|
+
resolvedBuildId,
|
|
657
|
+
platformName(platform),
|
|
658
|
+
"en-US",
|
|
659
|
+
archive2(platform, resolvedBuildId)
|
|
660
|
+
];
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
function relativeExecutablePath5(platform, buildId) {
|
|
664
|
+
const [channel] = parseBuildId(buildId);
|
|
665
|
+
switch (channel) {
|
|
666
|
+
case FirefoxChannel.NIGHTLY:
|
|
667
|
+
switch (platform) {
|
|
668
|
+
case BrowserPlatform.MAC_ARM:
|
|
669
|
+
case BrowserPlatform.MAC:
|
|
670
|
+
return path5.join("Firefox Nightly.app", "Contents", "MacOS", "firefox");
|
|
671
|
+
case BrowserPlatform.LINUX_ARM:
|
|
672
|
+
case BrowserPlatform.LINUX:
|
|
673
|
+
return path5.join("firefox", "firefox");
|
|
674
|
+
case BrowserPlatform.WIN32:
|
|
675
|
+
case BrowserPlatform.WIN64:
|
|
676
|
+
return path5.join("firefox", "firefox.exe");
|
|
677
|
+
}
|
|
678
|
+
case FirefoxChannel.BETA:
|
|
679
|
+
case FirefoxChannel.DEVEDITION:
|
|
680
|
+
case FirefoxChannel.ESR:
|
|
681
|
+
case FirefoxChannel.STABLE:
|
|
682
|
+
switch (platform) {
|
|
683
|
+
case BrowserPlatform.MAC_ARM:
|
|
684
|
+
case BrowserPlatform.MAC:
|
|
685
|
+
return path5.join("Firefox.app", "Contents", "MacOS", "firefox");
|
|
686
|
+
case BrowserPlatform.LINUX_ARM:
|
|
687
|
+
case BrowserPlatform.LINUX:
|
|
688
|
+
return path5.join("firefox", "firefox");
|
|
689
|
+
case BrowserPlatform.WIN32:
|
|
690
|
+
case BrowserPlatform.WIN64:
|
|
691
|
+
return path5.join("core", "firefox.exe");
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
var FirefoxChannel;
|
|
696
|
+
(function(FirefoxChannel2) {
|
|
697
|
+
FirefoxChannel2["STABLE"] = "stable";
|
|
698
|
+
FirefoxChannel2["ESR"] = "esr";
|
|
699
|
+
FirefoxChannel2["DEVEDITION"] = "devedition";
|
|
700
|
+
FirefoxChannel2["BETA"] = "beta";
|
|
701
|
+
FirefoxChannel2["NIGHTLY"] = "nightly";
|
|
702
|
+
})(FirefoxChannel || (FirefoxChannel = {}));
|
|
703
|
+
var baseVersionUrl2 = "https://product-details.mozilla.org/1.0";
|
|
704
|
+
async function resolveBuildId3(channel = FirefoxChannel.NIGHTLY) {
|
|
705
|
+
const channelToVersionKey = {
|
|
706
|
+
[FirefoxChannel.ESR]: "FIREFOX_ESR",
|
|
707
|
+
[FirefoxChannel.STABLE]: "LATEST_FIREFOX_VERSION",
|
|
708
|
+
[FirefoxChannel.DEVEDITION]: "FIREFOX_DEVEDITION",
|
|
709
|
+
[FirefoxChannel.BETA]: "FIREFOX_DEVEDITION",
|
|
710
|
+
[FirefoxChannel.NIGHTLY]: "FIREFOX_NIGHTLY"
|
|
711
|
+
};
|
|
712
|
+
const versions = await getJSON(new URL(`${baseVersionUrl2}/firefox_versions.json`));
|
|
713
|
+
const version = versions[channelToVersionKey[channel]];
|
|
714
|
+
if (!version) {
|
|
715
|
+
throw new Error(`Channel ${channel} is not found.`);
|
|
716
|
+
}
|
|
717
|
+
return channel + "_" + version;
|
|
718
|
+
}
|
|
719
|
+
async function createProfile(options) {
|
|
720
|
+
if (!fs.existsSync(options.path)) {
|
|
721
|
+
await fs.promises.mkdir(options.path, {
|
|
722
|
+
recursive: true
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
await syncPreferences({
|
|
726
|
+
preferences: {
|
|
727
|
+
...defaultProfilePreferences(options.preferences),
|
|
728
|
+
...options.preferences
|
|
729
|
+
},
|
|
730
|
+
path: options.path
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
function defaultProfilePreferences(extraPrefs) {
|
|
734
|
+
const server = "dummy.test";
|
|
735
|
+
const defaultPrefs = {
|
|
736
|
+
"app.normandy.api_url": "",
|
|
737
|
+
"app.update.checkInstallTime": false,
|
|
738
|
+
"app.update.disabledForTesting": true,
|
|
739
|
+
"apz.content_response_timeout": 60000,
|
|
740
|
+
"browser.contentblocking.features.standard": "-tp,tpPrivate,cookieBehavior0,-cryptoTP,-fp",
|
|
741
|
+
"browser.dom.window.dump.enabled": true,
|
|
742
|
+
"browser.newtabpage.activity-stream.feeds.system.topstories": false,
|
|
743
|
+
"browser.newtabpage.enabled": false,
|
|
744
|
+
"browser.pagethumbnails.capturing_disabled": true,
|
|
745
|
+
"browser.safebrowsing.blockedURIs.enabled": false,
|
|
746
|
+
"browser.safebrowsing.downloads.enabled": false,
|
|
747
|
+
"browser.safebrowsing.malware.enabled": false,
|
|
748
|
+
"browser.safebrowsing.phishing.enabled": false,
|
|
749
|
+
"browser.search.update": false,
|
|
750
|
+
"browser.sessionstore.resume_from_crash": false,
|
|
751
|
+
"browser.shell.checkDefaultBrowser": false,
|
|
752
|
+
"browser.startup.homepage": "about:blank",
|
|
753
|
+
"browser.startup.homepage_override.mstone": "ignore",
|
|
754
|
+
"browser.startup.page": 0,
|
|
755
|
+
"browser.tabs.disableBackgroundZombification": false,
|
|
756
|
+
"browser.tabs.warnOnCloseOtherTabs": false,
|
|
757
|
+
"browser.tabs.warnOnOpen": false,
|
|
758
|
+
"browser.translations.automaticallyPopup": false,
|
|
759
|
+
"browser.uitour.enabled": false,
|
|
760
|
+
"browser.urlbar.suggest.searches": false,
|
|
761
|
+
"browser.usedOnWindows10.introURL": "",
|
|
762
|
+
"browser.warnOnQuit": false,
|
|
763
|
+
"datareporting.healthreport.documentServerURI": `http://${server}/dummy/healthreport/`,
|
|
764
|
+
"datareporting.healthreport.logging.consoleEnabled": false,
|
|
765
|
+
"datareporting.healthreport.service.enabled": false,
|
|
766
|
+
"datareporting.healthreport.service.firstRun": false,
|
|
767
|
+
"datareporting.healthreport.uploadEnabled": false,
|
|
768
|
+
"datareporting.policy.dataSubmissionEnabled": false,
|
|
769
|
+
"datareporting.policy.dataSubmissionPolicyBypassNotification": true,
|
|
770
|
+
"devtools.jsonview.enabled": false,
|
|
771
|
+
"dom.disable_open_during_load": false,
|
|
772
|
+
"dom.file.createInChild": true,
|
|
773
|
+
"dom.ipc.reportProcessHangs": false,
|
|
774
|
+
"dom.max_chrome_script_run_time": 0,
|
|
775
|
+
"dom.max_script_run_time": 0,
|
|
776
|
+
"extensions.autoDisableScopes": 0,
|
|
777
|
+
"extensions.enabledScopes": 5,
|
|
778
|
+
"extensions.getAddons.cache.enabled": false,
|
|
779
|
+
"extensions.installDistroAddons": false,
|
|
780
|
+
"extensions.update.enabled": false,
|
|
781
|
+
"extensions.update.notifyUser": false,
|
|
782
|
+
"extensions.webservice.discoverURL": `http://${server}/dummy/discoveryURL`,
|
|
783
|
+
"focusmanager.testmode": true,
|
|
784
|
+
"general.useragent.updates.enabled": false,
|
|
785
|
+
"geo.provider.testing": true,
|
|
786
|
+
"geo.wifi.scan": false,
|
|
787
|
+
"hangmonitor.timeout": 0,
|
|
788
|
+
"javascript.options.showInConsole": true,
|
|
789
|
+
"media.gmp-manager.updateEnabled": false,
|
|
790
|
+
"media.sanity-test.disabled": true,
|
|
791
|
+
"network.cookie.sameSite.laxByDefault": false,
|
|
792
|
+
"network.http.prompt-temp-redirect": false,
|
|
793
|
+
"network.http.speculative-parallel-limit": 0,
|
|
794
|
+
"network.manage-offline-status": false,
|
|
795
|
+
"network.sntp.pools": server,
|
|
796
|
+
"plugin.state.flash": 0,
|
|
797
|
+
"privacy.trackingprotection.enabled": false,
|
|
798
|
+
"remote.enabled": true,
|
|
799
|
+
"remote.bidi.dismiss_file_pickers.enabled": true,
|
|
800
|
+
"screenshots.browser.component.enabled": false,
|
|
801
|
+
"security.certerrors.mitm.priming.enabled": false,
|
|
802
|
+
"security.fileuri.strict_origin_policy": false,
|
|
803
|
+
"security.notification_enable_delay": 0,
|
|
804
|
+
"services.settings.server": `http://${server}/dummy/blocklist/`,
|
|
805
|
+
"signon.autofillForms": false,
|
|
806
|
+
"signon.rememberSignons": false,
|
|
807
|
+
"startup.homepage_welcome_url": "about:blank",
|
|
808
|
+
"startup.homepage_welcome_url.additional": "",
|
|
809
|
+
"toolkit.cosmeticAnimations.enabled": false,
|
|
810
|
+
"toolkit.startup.max_resumed_crashes": -1
|
|
811
|
+
};
|
|
812
|
+
return Object.assign(defaultPrefs, extraPrefs);
|
|
813
|
+
}
|
|
814
|
+
async function backupFile(input) {
|
|
815
|
+
if (!fs.existsSync(input)) {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
await fs.promises.copyFile(input, input + ".puppeteer");
|
|
819
|
+
}
|
|
820
|
+
async function syncPreferences(options) {
|
|
821
|
+
const prefsPath = path5.join(options.path, "prefs.js");
|
|
822
|
+
const userPath = path5.join(options.path, "user.js");
|
|
823
|
+
const lines = Object.entries(options.preferences).map(([key, value]) => {
|
|
824
|
+
return `user_pref(${JSON.stringify(key)}, ${JSON.stringify(value)});`;
|
|
825
|
+
});
|
|
826
|
+
const result = await Promise.allSettled([
|
|
827
|
+
backupFile(userPath).then(async () => {
|
|
828
|
+
await fs.promises.writeFile(userPath, lines.join(`
|
|
829
|
+
`));
|
|
830
|
+
}),
|
|
831
|
+
backupFile(prefsPath)
|
|
832
|
+
]);
|
|
833
|
+
for (const command of result) {
|
|
834
|
+
if (command.status === "rejected") {
|
|
835
|
+
throw command.reason;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function compareVersions3(a, b) {
|
|
840
|
+
return parseInt(a.replace(".", ""), 16) - parseInt(b.replace(".", ""), 16);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// node_modules/@puppeteer/browsers/lib/browser-data/browser-data.js
|
|
844
|
+
var downloadUrls = {
|
|
845
|
+
[Browser.CHROMEDRIVER]: resolveDownloadUrl3,
|
|
846
|
+
[Browser.CHROMEHEADLESSSHELL]: resolveDownloadUrl2,
|
|
847
|
+
[Browser.CHROME]: resolveDownloadUrl,
|
|
848
|
+
[Browser.CHROMIUM]: resolveDownloadUrl4,
|
|
849
|
+
[Browser.FIREFOX]: resolveDownloadUrl5
|
|
850
|
+
};
|
|
851
|
+
var downloadPaths = {
|
|
852
|
+
[Browser.CHROMEDRIVER]: resolveDownloadPath3,
|
|
853
|
+
[Browser.CHROMEHEADLESSSHELL]: resolveDownloadPath2,
|
|
854
|
+
[Browser.CHROME]: resolveDownloadPath,
|
|
855
|
+
[Browser.CHROMIUM]: resolveDownloadPath4,
|
|
856
|
+
[Browser.FIREFOX]: resolveDownloadPath5
|
|
857
|
+
};
|
|
858
|
+
var executablePathByBrowser = {
|
|
859
|
+
[Browser.CHROMEDRIVER]: relativeExecutablePath3,
|
|
860
|
+
[Browser.CHROMEHEADLESSSHELL]: relativeExecutablePath2,
|
|
861
|
+
[Browser.CHROME]: relativeExecutablePath,
|
|
862
|
+
[Browser.CHROMIUM]: relativeExecutablePath4,
|
|
863
|
+
[Browser.FIREFOX]: relativeExecutablePath5
|
|
864
|
+
};
|
|
865
|
+
var versionComparators = {
|
|
866
|
+
[Browser.CHROMEDRIVER]: compareVersions,
|
|
867
|
+
[Browser.CHROMEHEADLESSSHELL]: compareVersions,
|
|
868
|
+
[Browser.CHROME]: compareVersions,
|
|
869
|
+
[Browser.CHROMIUM]: compareVersions2,
|
|
870
|
+
[Browser.FIREFOX]: compareVersions3
|
|
871
|
+
};
|
|
872
|
+
async function resolveBuildIdForBrowserTag(browser, platform, tag) {
|
|
873
|
+
switch (browser) {
|
|
874
|
+
case Browser.FIREFOX:
|
|
875
|
+
switch (tag) {
|
|
876
|
+
case BrowserTag.LATEST:
|
|
877
|
+
return await resolveBuildId3(FirefoxChannel.NIGHTLY);
|
|
878
|
+
case BrowserTag.BETA:
|
|
879
|
+
return await resolveBuildId3(FirefoxChannel.BETA);
|
|
880
|
+
case BrowserTag.NIGHTLY:
|
|
881
|
+
return await resolveBuildId3(FirefoxChannel.NIGHTLY);
|
|
882
|
+
case BrowserTag.DEVEDITION:
|
|
883
|
+
return await resolveBuildId3(FirefoxChannel.DEVEDITION);
|
|
884
|
+
case BrowserTag.STABLE:
|
|
885
|
+
return await resolveBuildId3(FirefoxChannel.STABLE);
|
|
886
|
+
case BrowserTag.ESR:
|
|
887
|
+
return await resolveBuildId3(FirefoxChannel.ESR);
|
|
888
|
+
case BrowserTag.CANARY:
|
|
889
|
+
case BrowserTag.DEV:
|
|
890
|
+
throw new Error(`${tag.toUpperCase()} is not available for Firefox`);
|
|
891
|
+
}
|
|
892
|
+
case Browser.CHROME: {
|
|
893
|
+
switch (tag) {
|
|
894
|
+
case BrowserTag.LATEST:
|
|
895
|
+
return await resolveBuildId(ChromeReleaseChannel.CANARY);
|
|
896
|
+
case BrowserTag.BETA:
|
|
897
|
+
return await resolveBuildId(ChromeReleaseChannel.BETA);
|
|
898
|
+
case BrowserTag.CANARY:
|
|
899
|
+
return await resolveBuildId(ChromeReleaseChannel.CANARY);
|
|
900
|
+
case BrowserTag.DEV:
|
|
901
|
+
return await resolveBuildId(ChromeReleaseChannel.DEV);
|
|
902
|
+
case BrowserTag.STABLE:
|
|
903
|
+
return await resolveBuildId(ChromeReleaseChannel.STABLE);
|
|
904
|
+
case BrowserTag.NIGHTLY:
|
|
905
|
+
case BrowserTag.DEVEDITION:
|
|
906
|
+
case BrowserTag.ESR:
|
|
907
|
+
throw new Error(`${tag.toUpperCase()} is not available for Chrome`);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
case Browser.CHROMEDRIVER: {
|
|
911
|
+
switch (tag) {
|
|
912
|
+
case BrowserTag.LATEST:
|
|
913
|
+
case BrowserTag.CANARY:
|
|
914
|
+
return await resolveBuildId(ChromeReleaseChannel.CANARY);
|
|
915
|
+
case BrowserTag.BETA:
|
|
916
|
+
return await resolveBuildId(ChromeReleaseChannel.BETA);
|
|
917
|
+
case BrowserTag.DEV:
|
|
918
|
+
return await resolveBuildId(ChromeReleaseChannel.DEV);
|
|
919
|
+
case BrowserTag.STABLE:
|
|
920
|
+
return await resolveBuildId(ChromeReleaseChannel.STABLE);
|
|
921
|
+
case BrowserTag.NIGHTLY:
|
|
922
|
+
case BrowserTag.DEVEDITION:
|
|
923
|
+
case BrowserTag.ESR:
|
|
924
|
+
throw new Error(`${tag.toUpperCase()} is not available for ChromeDriver`);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
case Browser.CHROMEHEADLESSSHELL: {
|
|
928
|
+
switch (tag) {
|
|
929
|
+
case BrowserTag.LATEST:
|
|
930
|
+
case BrowserTag.CANARY:
|
|
931
|
+
return await resolveBuildId(ChromeReleaseChannel.CANARY);
|
|
932
|
+
case BrowserTag.BETA:
|
|
933
|
+
return await resolveBuildId(ChromeReleaseChannel.BETA);
|
|
934
|
+
case BrowserTag.DEV:
|
|
935
|
+
return await resolveBuildId(ChromeReleaseChannel.DEV);
|
|
936
|
+
case BrowserTag.STABLE:
|
|
937
|
+
return await resolveBuildId(ChromeReleaseChannel.STABLE);
|
|
938
|
+
case BrowserTag.NIGHTLY:
|
|
939
|
+
case BrowserTag.DEVEDITION:
|
|
940
|
+
case BrowserTag.ESR:
|
|
941
|
+
throw new Error(`${tag} is not available for chrome-headless-shell`);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
case Browser.CHROMIUM:
|
|
945
|
+
switch (tag) {
|
|
946
|
+
case BrowserTag.LATEST:
|
|
947
|
+
return await resolveBuildId2(platform);
|
|
948
|
+
case BrowserTag.NIGHTLY:
|
|
949
|
+
case BrowserTag.CANARY:
|
|
950
|
+
case BrowserTag.DEV:
|
|
951
|
+
case BrowserTag.DEVEDITION:
|
|
952
|
+
case BrowserTag.BETA:
|
|
953
|
+
case BrowserTag.STABLE:
|
|
954
|
+
case BrowserTag.ESR:
|
|
955
|
+
throw new Error(`${tag} is not supported for Chromium. Use 'latest' instead.`);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
async function resolveBuildId4(browser, platform, tag) {
|
|
960
|
+
const browserTag = tag;
|
|
961
|
+
if (Object.values(BrowserTag).includes(browserTag)) {
|
|
962
|
+
return await resolveBuildIdForBrowserTag(browser, platform, browserTag);
|
|
963
|
+
}
|
|
964
|
+
switch (browser) {
|
|
965
|
+
case Browser.FIREFOX:
|
|
966
|
+
return tag;
|
|
967
|
+
case Browser.CHROME:
|
|
968
|
+
const chromeResult = await resolveBuildId(tag);
|
|
969
|
+
if (chromeResult) {
|
|
970
|
+
return chromeResult;
|
|
971
|
+
}
|
|
972
|
+
return tag;
|
|
973
|
+
case Browser.CHROMEDRIVER:
|
|
974
|
+
const chromeDriverResult = await resolveBuildId(tag);
|
|
975
|
+
if (chromeDriverResult) {
|
|
976
|
+
return chromeDriverResult;
|
|
977
|
+
}
|
|
978
|
+
return tag;
|
|
979
|
+
case Browser.CHROMEHEADLESSSHELL:
|
|
980
|
+
const chromeHeadlessShellResult = await resolveBuildId(tag);
|
|
981
|
+
if (chromeHeadlessShellResult) {
|
|
982
|
+
return chromeHeadlessShellResult;
|
|
983
|
+
}
|
|
984
|
+
return tag;
|
|
985
|
+
case Browser.CHROMIUM:
|
|
986
|
+
return tag;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
async function createProfile2(browser, opts) {
|
|
990
|
+
switch (browser) {
|
|
991
|
+
case Browser.FIREFOX:
|
|
992
|
+
return await createProfile(opts);
|
|
993
|
+
case Browser.CHROME:
|
|
994
|
+
case Browser.CHROMIUM:
|
|
995
|
+
throw new Error(`Profile creation is not support for ${browser} yet`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
function resolveDefaultUserDataDir2(browser, platform, channel) {
|
|
999
|
+
switch (browser) {
|
|
1000
|
+
case Browser.CHROMEDRIVER:
|
|
1001
|
+
case Browser.CHROMEHEADLESSSHELL:
|
|
1002
|
+
case Browser.FIREFOX:
|
|
1003
|
+
case Browser.CHROMIUM:
|
|
1004
|
+
throw new Error(`Default user dir detection is not supported for ${browser} yet.`);
|
|
1005
|
+
case Browser.CHROME:
|
|
1006
|
+
return resolveDefaultUserDataDir(platform, channel);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
function resolveSystemExecutablePaths2(browser, platform, channel) {
|
|
1010
|
+
switch (browser) {
|
|
1011
|
+
case Browser.CHROMEDRIVER:
|
|
1012
|
+
case Browser.CHROMEHEADLESSSHELL:
|
|
1013
|
+
case Browser.FIREFOX:
|
|
1014
|
+
case Browser.CHROMIUM:
|
|
1015
|
+
throw new Error(`System browser detection is not supported for ${browser} yet.`);
|
|
1016
|
+
case Browser.CHROME:
|
|
1017
|
+
return resolveSystemExecutablePaths(platform, channel);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
function getVersionComparator(browser) {
|
|
1021
|
+
return versionComparators[browser];
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// node_modules/@puppeteer/browsers/lib/Cache.js
|
|
1025
|
+
import fs2 from "node:fs";
|
|
1026
|
+
import os3 from "node:os";
|
|
1027
|
+
import path6 from "node:path";
|
|
1028
|
+
|
|
1029
|
+
// node_modules/@puppeteer/browsers/lib/debug.js
|
|
1030
|
+
import { debuglog } from "node:util";
|
|
1031
|
+
var debug = (prefix) => {
|
|
1032
|
+
const log = debuglog(prefix);
|
|
1033
|
+
return log.enabled ? log : undefined;
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
// node_modules/@puppeteer/browsers/lib/detectPlatform.js
|
|
1037
|
+
import os2 from "node:os";
|
|
1038
|
+
function detectBrowserPlatform() {
|
|
1039
|
+
const platform = os2.platform();
|
|
1040
|
+
const arch = os2.arch();
|
|
1041
|
+
switch (platform) {
|
|
1042
|
+
case "darwin":
|
|
1043
|
+
return arch === "arm64" ? BrowserPlatform.MAC_ARM : BrowserPlatform.MAC;
|
|
1044
|
+
case "linux":
|
|
1045
|
+
return arch === "arm64" ? BrowserPlatform.LINUX_ARM : BrowserPlatform.LINUX;
|
|
1046
|
+
case "win32":
|
|
1047
|
+
return arch === "x64" || arch === "arm64" && isWindows11(os2.release()) ? BrowserPlatform.WIN64 : BrowserPlatform.WIN32;
|
|
1048
|
+
default:
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
function isWindows11(version) {
|
|
1053
|
+
const parts = version.split(".");
|
|
1054
|
+
if (parts.length > 2) {
|
|
1055
|
+
const major = parseInt(parts[0], 10);
|
|
1056
|
+
const minor = parseInt(parts[1], 10);
|
|
1057
|
+
const patch = parseInt(parts[2], 10);
|
|
1058
|
+
return major > 10 || major === 10 && minor > 0 || major === 10 && minor === 0 && patch >= 22000;
|
|
1059
|
+
}
|
|
1060
|
+
return false;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// node_modules/@puppeteer/browsers/lib/Cache.js
|
|
1064
|
+
var debugCache = debug("puppeteer:browsers:cache");
|
|
1065
|
+
|
|
1066
|
+
class InstalledBrowser {
|
|
1067
|
+
browser;
|
|
1068
|
+
buildId;
|
|
1069
|
+
platform;
|
|
1070
|
+
executablePath;
|
|
1071
|
+
#cache;
|
|
1072
|
+
constructor(cache, browser, buildId, platform) {
|
|
1073
|
+
this.#cache = cache;
|
|
1074
|
+
this.browser = browser;
|
|
1075
|
+
this.buildId = buildId;
|
|
1076
|
+
this.platform = platform;
|
|
1077
|
+
this.executablePath = cache.computeExecutablePath({
|
|
1078
|
+
browser,
|
|
1079
|
+
buildId,
|
|
1080
|
+
platform
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
get path() {
|
|
1084
|
+
return this.#cache.installationDir(this.browser, this.platform, this.buildId);
|
|
1085
|
+
}
|
|
1086
|
+
readMetadata() {
|
|
1087
|
+
return this.#cache.readMetadata(this.browser);
|
|
1088
|
+
}
|
|
1089
|
+
writeMetadata(metadata) {
|
|
1090
|
+
this.#cache.writeMetadata(this.browser, metadata);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
class Cache {
|
|
1095
|
+
#rootDir;
|
|
1096
|
+
constructor(rootDir) {
|
|
1097
|
+
this.#rootDir = rootDir;
|
|
1098
|
+
}
|
|
1099
|
+
get rootDir() {
|
|
1100
|
+
return this.#rootDir;
|
|
1101
|
+
}
|
|
1102
|
+
browserRoot(browser) {
|
|
1103
|
+
return path6.join(this.#rootDir, browser);
|
|
1104
|
+
}
|
|
1105
|
+
metadataFile(browser) {
|
|
1106
|
+
return path6.join(this.browserRoot(browser), ".metadata");
|
|
1107
|
+
}
|
|
1108
|
+
readMetadata(browser) {
|
|
1109
|
+
const metatadaPath = this.metadataFile(browser);
|
|
1110
|
+
if (!fs2.existsSync(metatadaPath)) {
|
|
1111
|
+
return { aliases: {} };
|
|
1112
|
+
}
|
|
1113
|
+
const data = JSON.parse(fs2.readFileSync(metatadaPath, "utf8"));
|
|
1114
|
+
if (typeof data !== "object") {
|
|
1115
|
+
throw new Error(".metadata is not an object");
|
|
1116
|
+
}
|
|
1117
|
+
return data;
|
|
1118
|
+
}
|
|
1119
|
+
writeMetadata(browser, metadata) {
|
|
1120
|
+
const metatadaPath = this.metadataFile(browser);
|
|
1121
|
+
fs2.mkdirSync(path6.dirname(metatadaPath), { recursive: true });
|
|
1122
|
+
fs2.writeFileSync(metatadaPath, JSON.stringify(metadata, null, 2));
|
|
1123
|
+
}
|
|
1124
|
+
readExecutablePath(browser, platform, buildId) {
|
|
1125
|
+
const metadata = this.readMetadata(browser);
|
|
1126
|
+
const key = `${platform}-${buildId}`;
|
|
1127
|
+
return metadata.executablePaths?.[key] ?? null;
|
|
1128
|
+
}
|
|
1129
|
+
writeExecutablePath(browser, platform, buildId, executablePath) {
|
|
1130
|
+
const metadata = this.readMetadata(browser);
|
|
1131
|
+
if (!metadata.executablePaths) {
|
|
1132
|
+
metadata.executablePaths = {};
|
|
1133
|
+
}
|
|
1134
|
+
const key = `${platform}-${buildId}`;
|
|
1135
|
+
metadata.executablePaths[key] = executablePath;
|
|
1136
|
+
this.writeMetadata(browser, metadata);
|
|
1137
|
+
}
|
|
1138
|
+
resolveAlias(browser, alias) {
|
|
1139
|
+
const metadata = this.readMetadata(browser);
|
|
1140
|
+
if (alias === "latest") {
|
|
1141
|
+
return Object.values(metadata.aliases || {}).sort(getVersionComparator(browser)).at(-1);
|
|
1142
|
+
}
|
|
1143
|
+
return metadata.aliases[alias];
|
|
1144
|
+
}
|
|
1145
|
+
installationDir(browser, platform, buildId) {
|
|
1146
|
+
return path6.join(this.browserRoot(browser), `${platform}-${buildId}`);
|
|
1147
|
+
}
|
|
1148
|
+
clear() {
|
|
1149
|
+
fs2.rmSync(this.#rootDir, {
|
|
1150
|
+
force: true,
|
|
1151
|
+
recursive: true,
|
|
1152
|
+
maxRetries: 10,
|
|
1153
|
+
retryDelay: 500
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
uninstall(browser, platform, buildId) {
|
|
1157
|
+
const metadata = this.readMetadata(browser);
|
|
1158
|
+
for (const alias of Object.keys(metadata.aliases)) {
|
|
1159
|
+
if (metadata.aliases[alias] === buildId) {
|
|
1160
|
+
delete metadata.aliases[alias];
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
const key = `${platform}-${buildId}`;
|
|
1164
|
+
if (metadata.executablePaths?.[key]) {
|
|
1165
|
+
delete metadata.executablePaths[key];
|
|
1166
|
+
this.writeMetadata(browser, metadata);
|
|
1167
|
+
}
|
|
1168
|
+
fs2.rmSync(this.installationDir(browser, platform, buildId), {
|
|
1169
|
+
force: true,
|
|
1170
|
+
recursive: true,
|
|
1171
|
+
maxRetries: 10,
|
|
1172
|
+
retryDelay: 500
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
getInstalledBrowsers() {
|
|
1176
|
+
if (!fs2.existsSync(this.#rootDir)) {
|
|
1177
|
+
return [];
|
|
1178
|
+
}
|
|
1179
|
+
const types = fs2.readdirSync(this.#rootDir);
|
|
1180
|
+
const browsers = types.filter((t) => {
|
|
1181
|
+
return Object.values(Browser).includes(t);
|
|
1182
|
+
});
|
|
1183
|
+
return browsers.flatMap((browser) => {
|
|
1184
|
+
const files = fs2.readdirSync(this.browserRoot(browser));
|
|
1185
|
+
return files.map((file) => {
|
|
1186
|
+
const result = parseFolderPath(path6.join(this.browserRoot(browser), file));
|
|
1187
|
+
if (!result) {
|
|
1188
|
+
return null;
|
|
1189
|
+
}
|
|
1190
|
+
return new InstalledBrowser(this, browser, result.buildId, result.platform);
|
|
1191
|
+
}).filter((item) => {
|
|
1192
|
+
return item !== null;
|
|
1193
|
+
});
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
computeExecutablePath(options) {
|
|
1197
|
+
options.platform ??= detectBrowserPlatform();
|
|
1198
|
+
if (!options.platform) {
|
|
1199
|
+
throw new Error(`Cannot download a binary for the provided platform: ${os3.platform()} (${os3.arch()})`);
|
|
1200
|
+
}
|
|
1201
|
+
try {
|
|
1202
|
+
options.buildId = this.resolveAlias(options.browser, options.buildId) ?? options.buildId;
|
|
1203
|
+
} catch {
|
|
1204
|
+
debugCache?.("could not read .metadata file for the browser");
|
|
1205
|
+
}
|
|
1206
|
+
const installationDir = this.installationDir(options.browser, options.platform, options.buildId);
|
|
1207
|
+
const storedExecutablePath = this.readExecutablePath(options.browser, options.platform, options.buildId);
|
|
1208
|
+
if (storedExecutablePath) {
|
|
1209
|
+
return path6.join(installationDir, storedExecutablePath);
|
|
1210
|
+
}
|
|
1211
|
+
return path6.join(installationDir, executablePathByBrowser[options.browser](options.platform, options.buildId));
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
function parseFolderPath(folderPath) {
|
|
1215
|
+
const name = path6.basename(folderPath);
|
|
1216
|
+
const splits = name.split("-");
|
|
1217
|
+
if (splits.length !== 2) {
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
const [platform, buildId] = splits;
|
|
1221
|
+
if (!buildId || !platform) {
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
return { platform, buildId };
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// node_modules/@puppeteer/browsers/lib/launch.js
|
|
1228
|
+
var debugLaunch = debug("puppeteer:browsers:launcher");
|
|
1229
|
+
function computeExecutablePath(options) {
|
|
1230
|
+
if (options.cacheDir === null) {
|
|
1231
|
+
options.platform ??= detectBrowserPlatform();
|
|
1232
|
+
if (options.platform === undefined) {
|
|
1233
|
+
throw new Error(`No platform specified. Couldn't auto-detect browser platform.`);
|
|
1234
|
+
}
|
|
1235
|
+
return executablePathByBrowser[options.browser](options.platform, options.buildId);
|
|
1236
|
+
}
|
|
1237
|
+
return new Cache(options.cacheDir).computeExecutablePath(options);
|
|
1238
|
+
}
|
|
1239
|
+
function computeSystemExecutablePath(options) {
|
|
1240
|
+
options.platform ??= detectBrowserPlatform();
|
|
1241
|
+
if (!options.platform) {
|
|
1242
|
+
throw new Error(`Cannot download a binary for the provided platform: ${os4.platform()} (${os4.arch()})`);
|
|
1243
|
+
}
|
|
1244
|
+
const paths = resolveSystemExecutablePaths2(options.browser, options.platform, options.channel);
|
|
1245
|
+
for (const path7 of paths) {
|
|
1246
|
+
try {
|
|
1247
|
+
accessSync(path7);
|
|
1248
|
+
return path7;
|
|
1249
|
+
} catch {}
|
|
1250
|
+
}
|
|
1251
|
+
throw new Error(`Could not find Google Chrome executable for channel '${options.channel}' at:${paths.map((path7) => {
|
|
1252
|
+
return `
|
|
1253
|
+
- ${path7}`;
|
|
1254
|
+
})}.`);
|
|
1255
|
+
}
|
|
1256
|
+
function launch(opts) {
|
|
1257
|
+
return new Process(opts);
|
|
1258
|
+
}
|
|
1259
|
+
var CDP_WEBSOCKET_ENDPOINT_REGEX = /^DevTools listening on (ws:\/\/.*)$/;
|
|
1260
|
+
var WEBDRIVER_BIDI_WEBSOCKET_ENDPOINT_REGEX = /^WebDriver BiDi listening on (ws:\/\/.*)$/;
|
|
1261
|
+
var processListeners = new Map;
|
|
1262
|
+
var dispatchers = {
|
|
1263
|
+
exit: (...args) => {
|
|
1264
|
+
processListeners.get("exit")?.forEach((handler) => {
|
|
1265
|
+
return handler(...args);
|
|
1266
|
+
});
|
|
1267
|
+
},
|
|
1268
|
+
SIGINT: (...args) => {
|
|
1269
|
+
processListeners.get("SIGINT")?.forEach((handler) => {
|
|
1270
|
+
return handler(...args);
|
|
1271
|
+
});
|
|
1272
|
+
},
|
|
1273
|
+
SIGHUP: (...args) => {
|
|
1274
|
+
processListeners.get("SIGHUP")?.forEach((handler) => {
|
|
1275
|
+
return handler(...args);
|
|
1276
|
+
});
|
|
1277
|
+
},
|
|
1278
|
+
SIGTERM: (...args) => {
|
|
1279
|
+
processListeners.get("SIGTERM")?.forEach((handler) => {
|
|
1280
|
+
return handler(...args);
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
function subscribeToProcessEvent(event, handler) {
|
|
1285
|
+
const listeners = processListeners.get(event) || [];
|
|
1286
|
+
if (listeners.length === 0) {
|
|
1287
|
+
process.on(event, dispatchers[event]);
|
|
1288
|
+
}
|
|
1289
|
+
listeners.push(handler);
|
|
1290
|
+
processListeners.set(event, listeners);
|
|
1291
|
+
}
|
|
1292
|
+
function unsubscribeFromProcessEvent(event, handler) {
|
|
1293
|
+
const listeners = processListeners.get(event) || [];
|
|
1294
|
+
const existingListenerIdx = listeners.indexOf(handler);
|
|
1295
|
+
if (existingListenerIdx === -1) {
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
listeners.splice(existingListenerIdx, 1);
|
|
1299
|
+
processListeners.set(event, listeners);
|
|
1300
|
+
if (listeners.length === 0) {
|
|
1301
|
+
process.off(event, dispatchers[event]);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
class Process {
|
|
1306
|
+
#executablePath;
|
|
1307
|
+
#args;
|
|
1308
|
+
#browserProcess;
|
|
1309
|
+
#exited = false;
|
|
1310
|
+
#hooksRan = false;
|
|
1311
|
+
#onExitHook = async () => {};
|
|
1312
|
+
#browserProcessExiting;
|
|
1313
|
+
#logs = [];
|
|
1314
|
+
#maxLogLinesSize = 1000;
|
|
1315
|
+
#lineEmitter = new EventEmitter;
|
|
1316
|
+
#onAbort = () => {
|
|
1317
|
+
this.kill();
|
|
1318
|
+
};
|
|
1319
|
+
#signal;
|
|
1320
|
+
constructor(opts) {
|
|
1321
|
+
this.#executablePath = opts.executablePath;
|
|
1322
|
+
this.#args = opts.args ?? [];
|
|
1323
|
+
this.#signal = opts.signal;
|
|
1324
|
+
if (this.#signal?.aborted) {
|
|
1325
|
+
throw new Error(this.#signal.reason ? this.#signal.reason : "Launch aborted");
|
|
1326
|
+
}
|
|
1327
|
+
this.#signal?.addEventListener("abort", this.#onAbort, { once: true });
|
|
1328
|
+
opts.pipe ??= false;
|
|
1329
|
+
opts.dumpio ??= false;
|
|
1330
|
+
opts.handleSIGINT ??= true;
|
|
1331
|
+
opts.handleSIGTERM ??= true;
|
|
1332
|
+
opts.handleSIGHUP ??= true;
|
|
1333
|
+
opts.detached ??= process.platform !== "win32";
|
|
1334
|
+
const stdio = this.#configureStdio({
|
|
1335
|
+
pipe: opts.pipe
|
|
1336
|
+
});
|
|
1337
|
+
const env = opts.env || {};
|
|
1338
|
+
debugLaunch?.(`Launching ${this.#executablePath} ${this.#args.join(" ")}`, {
|
|
1339
|
+
detached: opts.detached,
|
|
1340
|
+
env: Object.keys(env).reduce((res, key) => {
|
|
1341
|
+
if (key.toLowerCase().startsWith("puppeteer_")) {
|
|
1342
|
+
res[key] = env[key];
|
|
1343
|
+
}
|
|
1344
|
+
return res;
|
|
1345
|
+
}, {}),
|
|
1346
|
+
stdio
|
|
1347
|
+
});
|
|
1348
|
+
this.#browserProcess = childProcess.spawn(this.#executablePath, this.#args, {
|
|
1349
|
+
detached: opts.detached,
|
|
1350
|
+
env,
|
|
1351
|
+
stdio
|
|
1352
|
+
});
|
|
1353
|
+
this.#recordStream(this.#browserProcess.stderr);
|
|
1354
|
+
this.#recordStream(this.#browserProcess.stdout);
|
|
1355
|
+
debugLaunch?.(`Launched ${this.#browserProcess.pid}`);
|
|
1356
|
+
if (opts.dumpio) {
|
|
1357
|
+
this.#browserProcess.stderr?.pipe(process.stderr);
|
|
1358
|
+
this.#browserProcess.stdout?.pipe(process.stdout);
|
|
1359
|
+
}
|
|
1360
|
+
subscribeToProcessEvent("exit", this.#onDriverProcessExit);
|
|
1361
|
+
if (opts.handleSIGINT) {
|
|
1362
|
+
subscribeToProcessEvent("SIGINT", this.#onDriverProcessSignal);
|
|
1363
|
+
}
|
|
1364
|
+
if (opts.handleSIGTERM) {
|
|
1365
|
+
subscribeToProcessEvent("SIGTERM", this.#onDriverProcessSignal);
|
|
1366
|
+
}
|
|
1367
|
+
if (opts.handleSIGHUP) {
|
|
1368
|
+
subscribeToProcessEvent("SIGHUP", this.#onDriverProcessSignal);
|
|
1369
|
+
}
|
|
1370
|
+
if (opts.onExit) {
|
|
1371
|
+
this.#onExitHook = opts.onExit;
|
|
1372
|
+
}
|
|
1373
|
+
this.#browserProcessExiting = new Promise((resolve, reject) => {
|
|
1374
|
+
this.#browserProcess.once("exit", async () => {
|
|
1375
|
+
debugLaunch?.(`Browser process ${this.#browserProcess.pid} onExit`);
|
|
1376
|
+
this.#clearListeners();
|
|
1377
|
+
this.#exited = true;
|
|
1378
|
+
try {
|
|
1379
|
+
await this.#runHooks();
|
|
1380
|
+
} catch (err) {
|
|
1381
|
+
reject(err);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
resolve();
|
|
1385
|
+
});
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
async#runHooks() {
|
|
1389
|
+
if (this.#hooksRan) {
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
this.#hooksRan = true;
|
|
1393
|
+
await this.#onExitHook();
|
|
1394
|
+
}
|
|
1395
|
+
get nodeProcess() {
|
|
1396
|
+
return this.#browserProcess;
|
|
1397
|
+
}
|
|
1398
|
+
#configureStdio(opts) {
|
|
1399
|
+
if (opts.pipe) {
|
|
1400
|
+
return ["pipe", "pipe", "pipe", "pipe", "pipe"];
|
|
1401
|
+
} else {
|
|
1402
|
+
return ["pipe", "pipe", "pipe"];
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
#clearListeners() {
|
|
1406
|
+
unsubscribeFromProcessEvent("exit", this.#onDriverProcessExit);
|
|
1407
|
+
unsubscribeFromProcessEvent("SIGINT", this.#onDriverProcessSignal);
|
|
1408
|
+
unsubscribeFromProcessEvent("SIGTERM", this.#onDriverProcessSignal);
|
|
1409
|
+
unsubscribeFromProcessEvent("SIGHUP", this.#onDriverProcessSignal);
|
|
1410
|
+
this.#signal?.removeEventListener("abort", this.#onAbort);
|
|
1411
|
+
}
|
|
1412
|
+
#onDriverProcessExit = (_code) => {
|
|
1413
|
+
this.kill();
|
|
1414
|
+
};
|
|
1415
|
+
#onDriverProcessSignal = (signal) => {
|
|
1416
|
+
switch (signal) {
|
|
1417
|
+
case "SIGINT":
|
|
1418
|
+
this.kill();
|
|
1419
|
+
process.exit(130);
|
|
1420
|
+
case "SIGTERM":
|
|
1421
|
+
case "SIGHUP":
|
|
1422
|
+
this.close();
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
async close() {
|
|
1427
|
+
await this.#runHooks();
|
|
1428
|
+
if (!this.#exited) {
|
|
1429
|
+
this.kill();
|
|
1430
|
+
}
|
|
1431
|
+
return await this.#browserProcessExiting;
|
|
1432
|
+
}
|
|
1433
|
+
hasClosed() {
|
|
1434
|
+
return this.#browserProcessExiting;
|
|
1435
|
+
}
|
|
1436
|
+
kill() {
|
|
1437
|
+
debugLaunch?.(`Trying to kill ${this.#browserProcess.pid}`);
|
|
1438
|
+
if (this.#browserProcess && this.#browserProcess.pid && pidExists(this.#browserProcess.pid)) {
|
|
1439
|
+
try {
|
|
1440
|
+
debugLaunch?.(`Browser process ${this.#browserProcess.pid} exists`);
|
|
1441
|
+
if (process.platform === "win32") {
|
|
1442
|
+
try {
|
|
1443
|
+
childProcess.execSync(`taskkill /pid ${this.#browserProcess.pid} /T /F`);
|
|
1444
|
+
} catch (error) {
|
|
1445
|
+
debugLaunch?.(`Killing ${this.#browserProcess.pid} using taskkill failed`, error);
|
|
1446
|
+
this.#browserProcess.kill();
|
|
1447
|
+
}
|
|
1448
|
+
} else {
|
|
1449
|
+
const processGroupId = -this.#browserProcess.pid;
|
|
1450
|
+
try {
|
|
1451
|
+
process.kill(processGroupId, "SIGKILL");
|
|
1452
|
+
} catch (error) {
|
|
1453
|
+
debugLaunch?.(`Killing ${this.#browserProcess.pid} using process.kill failed`, error);
|
|
1454
|
+
this.#browserProcess.kill("SIGKILL");
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
} catch (error) {
|
|
1458
|
+
throw new Error(`${PROCESS_ERROR_EXPLANATION}
|
|
1459
|
+
Error cause: ${isErrorLike(error) ? error.stack : error}`);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
this.#clearListeners();
|
|
1463
|
+
}
|
|
1464
|
+
#recordStream(stream) {
|
|
1465
|
+
const rl = readline.createInterface(stream);
|
|
1466
|
+
const cleanup = () => {
|
|
1467
|
+
rl.off("line", onLine);
|
|
1468
|
+
rl.off("close", onClose);
|
|
1469
|
+
try {
|
|
1470
|
+
rl.close();
|
|
1471
|
+
} catch {}
|
|
1472
|
+
};
|
|
1473
|
+
const onLine = (line) => {
|
|
1474
|
+
if (line.trim() === "") {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
this.#logs.push(line);
|
|
1478
|
+
const delta = this.#logs.length - this.#maxLogLinesSize;
|
|
1479
|
+
if (delta) {
|
|
1480
|
+
this.#logs.splice(0, delta);
|
|
1481
|
+
}
|
|
1482
|
+
this.#lineEmitter.emit("line", line);
|
|
1483
|
+
};
|
|
1484
|
+
const onClose = () => {
|
|
1485
|
+
cleanup();
|
|
1486
|
+
};
|
|
1487
|
+
rl.on("line", onLine);
|
|
1488
|
+
rl.on("close", onClose);
|
|
1489
|
+
}
|
|
1490
|
+
getRecentLogs() {
|
|
1491
|
+
return [...this.#logs];
|
|
1492
|
+
}
|
|
1493
|
+
waitForLineOutput(regex, timeout = 0) {
|
|
1494
|
+
return new Promise((resolve, reject) => {
|
|
1495
|
+
const onClose = (errorOrCode) => {
|
|
1496
|
+
cleanup();
|
|
1497
|
+
reject(new Error([
|
|
1498
|
+
`Failed to launch the browser process: ${errorOrCode instanceof Error ? ` ${errorOrCode.message}` : ` Code: ${errorOrCode}`}`,
|
|
1499
|
+
"",
|
|
1500
|
+
`stderr:`,
|
|
1501
|
+
this.getRecentLogs().join(`
|
|
1502
|
+
`),
|
|
1503
|
+
"",
|
|
1504
|
+
"TROUBLESHOOTING: https://pptr.dev/troubleshooting",
|
|
1505
|
+
""
|
|
1506
|
+
].join(`
|
|
1507
|
+
`)));
|
|
1508
|
+
};
|
|
1509
|
+
this.#browserProcess.on("exit", onClose);
|
|
1510
|
+
this.#browserProcess.on("error", onClose);
|
|
1511
|
+
const timeoutId = timeout > 0 ? setTimeout(onTimeout, timeout) : undefined;
|
|
1512
|
+
this.#lineEmitter.on("line", onLine);
|
|
1513
|
+
const cleanup = () => {
|
|
1514
|
+
clearTimeout(timeoutId);
|
|
1515
|
+
this.#lineEmitter.off("line", onLine);
|
|
1516
|
+
this.#browserProcess.off("exit", onClose);
|
|
1517
|
+
this.#browserProcess.off("error", onClose);
|
|
1518
|
+
};
|
|
1519
|
+
function onTimeout() {
|
|
1520
|
+
cleanup();
|
|
1521
|
+
reject(new TimeoutError(`Timed out after ${timeout} ms while waiting for the WS endpoint URL to appear in stdout!`));
|
|
1522
|
+
}
|
|
1523
|
+
for (const line of this.#logs) {
|
|
1524
|
+
onLine(line);
|
|
1525
|
+
}
|
|
1526
|
+
function onLine(line) {
|
|
1527
|
+
const match = line.match(regex);
|
|
1528
|
+
if (!match) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
cleanup();
|
|
1532
|
+
resolve(match[1]);
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
var PROCESS_ERROR_EXPLANATION = `Puppeteer was unable to kill the process which ran the browser binary.
|
|
1538
|
+
This means that, on future Puppeteer launches, Puppeteer might not be able to launch the browser.
|
|
1539
|
+
Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed.
|
|
1540
|
+
If you think this is a bug, please report it on the Puppeteer issue tracker.`;
|
|
1541
|
+
function pidExists(pid) {
|
|
1542
|
+
try {
|
|
1543
|
+
return process.kill(pid, 0);
|
|
1544
|
+
} catch (error) {
|
|
1545
|
+
if (isErrnoException(error)) {
|
|
1546
|
+
if (error.code && error.code === "ESRCH") {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
throw error;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
function isErrorLike(obj) {
|
|
1554
|
+
return typeof obj === "object" && obj !== null && "name" in obj && "message" in obj;
|
|
1555
|
+
}
|
|
1556
|
+
function isErrnoException(obj) {
|
|
1557
|
+
return isErrorLike(obj) && (("errno" in obj) || ("code" in obj) || ("path" in obj) || ("syscall" in obj));
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
class TimeoutError extends Error {
|
|
1561
|
+
constructor(message) {
|
|
1562
|
+
super(message);
|
|
1563
|
+
this.name = this.constructor.name;
|
|
1564
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
// node_modules/@puppeteer/browsers/lib/install.js
|
|
1568
|
+
import assert from "node:assert";
|
|
1569
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1570
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1571
|
+
import { mkdir as mkdir2, unlink } from "node:fs/promises";
|
|
1572
|
+
import os5 from "node:os";
|
|
1573
|
+
import path8 from "node:path";
|
|
1574
|
+
|
|
1575
|
+
// node_modules/@puppeteer/browsers/lib/DefaultProvider.js
|
|
1576
|
+
class DefaultProvider {
|
|
1577
|
+
#baseUrl;
|
|
1578
|
+
constructor(baseUrl) {
|
|
1579
|
+
this.#baseUrl = baseUrl;
|
|
1580
|
+
}
|
|
1581
|
+
supports(_options) {
|
|
1582
|
+
return true;
|
|
1583
|
+
}
|
|
1584
|
+
getDownloadUrl(options) {
|
|
1585
|
+
return this.#getDownloadUrl(options.browser, options.platform, options.buildId);
|
|
1586
|
+
}
|
|
1587
|
+
#getDownloadUrl(browser, platform, buildId) {
|
|
1588
|
+
return new URL(downloadUrls[browser](platform, buildId, this.#baseUrl));
|
|
1589
|
+
}
|
|
1590
|
+
getExecutablePath(options) {
|
|
1591
|
+
return executablePathByBrowser[options.browser](options.platform, options.buildId);
|
|
1592
|
+
}
|
|
1593
|
+
getName() {
|
|
1594
|
+
return "DefaultProvider";
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// node_modules/@puppeteer/browsers/lib/fileUtil.js
|
|
1599
|
+
import { spawnSync, spawn, execFile } from "node:child_process";
|
|
1600
|
+
import { createReadStream } from "node:fs";
|
|
1601
|
+
import { mkdir, readdir } from "node:fs/promises";
|
|
1602
|
+
import * as path7 from "node:path";
|
|
1603
|
+
import { Stream } from "node:stream";
|
|
1604
|
+
import { promisify } from "node:util";
|
|
1605
|
+
var execFileAsync = promisify(execFile);
|
|
1606
|
+
var debugFileUtil = debug("puppeteer:browsers:fileUtil");
|
|
1607
|
+
async function unpackArchive(archivePath, folderPath) {
|
|
1608
|
+
if (!path7.isAbsolute(folderPath)) {
|
|
1609
|
+
folderPath = path7.resolve(process.cwd(), folderPath);
|
|
1610
|
+
}
|
|
1611
|
+
if (archivePath.endsWith(".zip")) {
|
|
1612
|
+
await mkdir(folderPath, { recursive: true });
|
|
1613
|
+
await extractZip(archivePath, folderPath);
|
|
1614
|
+
} else if (archivePath.endsWith(".tar.bz2")) {
|
|
1615
|
+
await extractTar(archivePath, folderPath, "bzip2");
|
|
1616
|
+
} else if (archivePath.endsWith(".dmg")) {
|
|
1617
|
+
await mkdir(folderPath);
|
|
1618
|
+
await installDMG(archivePath, folderPath);
|
|
1619
|
+
} else if (archivePath.endsWith(".exe")) {
|
|
1620
|
+
const result = spawnSync(archivePath, [`/ExtractDir=${folderPath}`], {
|
|
1621
|
+
env: {
|
|
1622
|
+
__compat_layer: "RunAsInvoker"
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
if (result.status !== 0) {
|
|
1626
|
+
throw new Error(`Failed to extract ${archivePath} to ${folderPath}: ${result.output}`);
|
|
1627
|
+
}
|
|
1628
|
+
} else if (archivePath.endsWith(".tar.xz")) {
|
|
1629
|
+
await extractTar(archivePath, folderPath, "xz");
|
|
1630
|
+
} else {
|
|
1631
|
+
throw new Error(`Unsupported archive format: ${archivePath}`);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
function createTransformStream(child) {
|
|
1635
|
+
const stream = new Stream.Transform({
|
|
1636
|
+
transform(chunk, encoding, callback) {
|
|
1637
|
+
if (!child.stdin.write(chunk, encoding)) {
|
|
1638
|
+
child.stdin.once("drain", callback);
|
|
1639
|
+
} else {
|
|
1640
|
+
callback();
|
|
1641
|
+
}
|
|
1642
|
+
},
|
|
1643
|
+
flush(callback) {
|
|
1644
|
+
if (child.stdout.destroyed) {
|
|
1645
|
+
callback();
|
|
1646
|
+
} else {
|
|
1647
|
+
child.stdin.end();
|
|
1648
|
+
child.stdout.on("close", callback);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
});
|
|
1652
|
+
child.stdin.on("error", (e) => {
|
|
1653
|
+
if ("code" in e && e.code === "EPIPE") {
|
|
1654
|
+
stream.emit("end");
|
|
1655
|
+
} else {
|
|
1656
|
+
stream.destroy(e);
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
child.stdout.on("data", (data) => {
|
|
1660
|
+
return stream.push(data);
|
|
1661
|
+
}).on("error", (e) => {
|
|
1662
|
+
return stream.destroy(e);
|
|
1663
|
+
});
|
|
1664
|
+
child.once("close", () => {
|
|
1665
|
+
return stream.end();
|
|
1666
|
+
});
|
|
1667
|
+
return stream;
|
|
1668
|
+
}
|
|
1669
|
+
var internalConstantsForTesting = {
|
|
1670
|
+
xz: "xz",
|
|
1671
|
+
bzip2: "bzip2"
|
|
1672
|
+
};
|
|
1673
|
+
async function extractTar(tarPath, folderPath, decompressUtilityName) {
|
|
1674
|
+
const { unpackTar } = await import("./index-gp8nzd9n.mjs");
|
|
1675
|
+
return await new Promise((fulfill, reject) => {
|
|
1676
|
+
function handleError(utilityName) {
|
|
1677
|
+
return (error) => {
|
|
1678
|
+
if ("code" in error && error.code === "ENOENT") {
|
|
1679
|
+
error = new Error(`\`${utilityName}\` utility is required to unpack this archive`, {
|
|
1680
|
+
cause: error
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
reject(error);
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
const unpack = spawn(internalConstantsForTesting[decompressUtilityName], ["-d"], {
|
|
1687
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
1688
|
+
}).once("error", handleError(decompressUtilityName)).once("exit", (code) => {
|
|
1689
|
+
debugFileUtil?.(`${decompressUtilityName} exited, code=${code}`);
|
|
1690
|
+
});
|
|
1691
|
+
const tar = unpackTar(folderPath);
|
|
1692
|
+
tar.once("error", handleError("tar"));
|
|
1693
|
+
tar.once("finish", fulfill);
|
|
1694
|
+
createReadStream(tarPath).pipe(createTransformStream(unpack)).pipe(tar);
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
async function installDMG(dmgPath, folderPath) {
|
|
1698
|
+
const { stdout } = await execFileAsync("hdiutil", [
|
|
1699
|
+
"attach",
|
|
1700
|
+
"-nobrowse",
|
|
1701
|
+
"-noautoopen",
|
|
1702
|
+
dmgPath
|
|
1703
|
+
]);
|
|
1704
|
+
const volumes = stdout.match(/\/Volumes\/(.*)/m);
|
|
1705
|
+
if (!volumes) {
|
|
1706
|
+
throw new Error(`Could not find volume path in ${stdout}`);
|
|
1707
|
+
}
|
|
1708
|
+
const mountPath = volumes[0];
|
|
1709
|
+
try {
|
|
1710
|
+
const fileNames = await readdir(mountPath);
|
|
1711
|
+
const appName = fileNames.find((item) => {
|
|
1712
|
+
return typeof item === "string" && item.endsWith(".app");
|
|
1713
|
+
});
|
|
1714
|
+
if (!appName) {
|
|
1715
|
+
throw new Error(`Cannot find app in ${mountPath}`);
|
|
1716
|
+
}
|
|
1717
|
+
const mountedPath = path7.join(mountPath, appName);
|
|
1718
|
+
await execFileAsync("cp", ["-R", mountedPath, folderPath]);
|
|
1719
|
+
} finally {
|
|
1720
|
+
await execFileAsync("hdiutil", ["detach", mountPath, "-quiet"]);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
async function extractZip(archivePath, folderPath) {
|
|
1724
|
+
try {
|
|
1725
|
+
if (process.platform === "win32") {
|
|
1726
|
+
const systemRoot = process.env["SystemRoot"] ?? process.env["SYSTEMROOT"] ?? "C:\\Windows";
|
|
1727
|
+
try {
|
|
1728
|
+
const systemTar = `${systemRoot}\\System32\\tar.exe`;
|
|
1729
|
+
await execFileAsync(systemTar, ["-xf", archivePath, "-C", folderPath]);
|
|
1730
|
+
return;
|
|
1731
|
+
} catch (tarError) {
|
|
1732
|
+
debugFileUtil?.(`tar.exe extraction failed: ${tarError}`);
|
|
1733
|
+
}
|
|
1734
|
+
try {
|
|
1735
|
+
await execFileAsync("powershell.exe", [
|
|
1736
|
+
"-NoProfile",
|
|
1737
|
+
"-NonInteractive",
|
|
1738
|
+
"-Command",
|
|
1739
|
+
"& { Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force }",
|
|
1740
|
+
archivePath,
|
|
1741
|
+
folderPath
|
|
1742
|
+
]);
|
|
1743
|
+
return;
|
|
1744
|
+
} catch (powershellError) {
|
|
1745
|
+
debugFileUtil?.(`powershell.exe extraction failed: ${powershellError}`);
|
|
1746
|
+
}
|
|
1747
|
+
await execFileAsync("pwsh.exe", [
|
|
1748
|
+
"-NoProfile",
|
|
1749
|
+
"-NonInteractive",
|
|
1750
|
+
"-Command",
|
|
1751
|
+
"& { Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force }",
|
|
1752
|
+
archivePath,
|
|
1753
|
+
folderPath
|
|
1754
|
+
]);
|
|
1755
|
+
} else {
|
|
1756
|
+
await execFileAsync("unzip", ["-o", archivePath, "-d", folderPath]);
|
|
1757
|
+
}
|
|
1758
|
+
} catch (error) {
|
|
1759
|
+
if (error?.code === "ENOENT") {
|
|
1760
|
+
throw new Error(`Extraction failed: Required native binary ('tar.exe', 'powershell.exe', 'pwsh.exe' or 'unzip') was not found in the system PATH.`);
|
|
1761
|
+
}
|
|
1762
|
+
throw new Error(`Extraction failed: ${error?.stderr?.toString() || error?.message}`);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
// node_modules/@puppeteer/browsers/lib/ProgressBar.js
|
|
1767
|
+
var activeBar = null;
|
|
1768
|
+
|
|
1769
|
+
class ProgressBar {
|
|
1770
|
+
#stream;
|
|
1771
|
+
#totalRows = 0;
|
|
1772
|
+
#doneCount = 0;
|
|
1773
|
+
#bars = [];
|
|
1774
|
+
#renderScheduled = false;
|
|
1775
|
+
#lastRenderTime = 0;
|
|
1776
|
+
#allDone = false;
|
|
1777
|
+
constructor(stream) {
|
|
1778
|
+
this.#stream = stream;
|
|
1779
|
+
}
|
|
1780
|
+
static createBarTicker(title, total, stream = process.stderr) {
|
|
1781
|
+
if (!activeBar || activeBar.#stream !== stream) {
|
|
1782
|
+
activeBar = new ProgressBar(stream);
|
|
1783
|
+
}
|
|
1784
|
+
return activeBar.#addBar(title, total);
|
|
1785
|
+
}
|
|
1786
|
+
#claimRow() {
|
|
1787
|
+
const row = this.#totalRows++;
|
|
1788
|
+
if (row > 0 && this.#stream.isTTY) {
|
|
1789
|
+
this.#stream.write(`
|
|
1790
|
+
`);
|
|
1791
|
+
}
|
|
1792
|
+
return row;
|
|
1793
|
+
}
|
|
1794
|
+
#addBar(title, total) {
|
|
1795
|
+
const row = this.#claimRow();
|
|
1796
|
+
this.#bars.push({
|
|
1797
|
+
title,
|
|
1798
|
+
total,
|
|
1799
|
+
downloaded: 0,
|
|
1800
|
+
startTime: 0,
|
|
1801
|
+
lastRendered: ""
|
|
1802
|
+
});
|
|
1803
|
+
let doneNotified = false;
|
|
1804
|
+
return (delta) => {
|
|
1805
|
+
const bar = this.#bars[row];
|
|
1806
|
+
if (bar.startTime === 0) {
|
|
1807
|
+
bar.startTime = Date.now();
|
|
1808
|
+
}
|
|
1809
|
+
bar.downloaded += delta;
|
|
1810
|
+
const isDone = bar.downloaded >= bar.total;
|
|
1811
|
+
if (isDone || Date.now() - this.#lastRenderTime >= 100) {
|
|
1812
|
+
this.#scheduleRender();
|
|
1813
|
+
}
|
|
1814
|
+
if (isDone && !doneNotified) {
|
|
1815
|
+
doneNotified = true;
|
|
1816
|
+
this.#onBarDone();
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
#scheduleRender() {
|
|
1821
|
+
if (!this.#renderScheduled) {
|
|
1822
|
+
this.#renderScheduled = true;
|
|
1823
|
+
queueMicrotask(() => {
|
|
1824
|
+
this.#renderScheduled = false;
|
|
1825
|
+
this.#lastRenderTime = Date.now();
|
|
1826
|
+
this.#renderAll();
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
#computeRendered(row) {
|
|
1831
|
+
const bar = this.#bars[row];
|
|
1832
|
+
const ratio = Math.min(1, Math.max(0, bar.downloaded / bar.total));
|
|
1833
|
+
const percent = Math.round(ratio * 100);
|
|
1834
|
+
const elapsedMs = bar.startTime > 0 ? Date.now() - bar.startTime : 0;
|
|
1835
|
+
const rate = elapsedMs > 0 ? bar.downloaded / elapsedMs : 0;
|
|
1836
|
+
const etaSec = rate > 0 ? (bar.total - bar.downloaded) / rate / 1000 : 0;
|
|
1837
|
+
const width = 20;
|
|
1838
|
+
const completeCount = Math.round(width * ratio);
|
|
1839
|
+
const barStr = "=".repeat(completeCount) + " ".repeat(width - completeCount);
|
|
1840
|
+
const status = ratio >= 1 ? "unpacking" : `${percent}% ${etaSec.toFixed(1)}s`;
|
|
1841
|
+
return `${bar.title} [${barStr}] ${status} `;
|
|
1842
|
+
}
|
|
1843
|
+
#renderAll() {
|
|
1844
|
+
if (!this.#stream.isTTY) {
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
const N = this.#totalRows;
|
|
1848
|
+
if (N === 0) {
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
if (N > 1) {
|
|
1852
|
+
this.#stream.moveCursor(0, -(N - 1));
|
|
1853
|
+
}
|
|
1854
|
+
for (let row = 0;row < N; row++) {
|
|
1855
|
+
const rendered = this.#computeRendered(row);
|
|
1856
|
+
if (rendered !== this.#bars[row].lastRendered) {
|
|
1857
|
+
this.#stream.cursorTo(0);
|
|
1858
|
+
this.#stream.write(rendered);
|
|
1859
|
+
this.#stream.clearLine(1);
|
|
1860
|
+
this.#bars[row].lastRendered = rendered;
|
|
1861
|
+
}
|
|
1862
|
+
if (row < N - 1) {
|
|
1863
|
+
this.#stream.moveCursor(0, 1);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
this.#stream.cursorTo(0);
|
|
1867
|
+
if (this.#allDone) {
|
|
1868
|
+
activeBar = null;
|
|
1869
|
+
this.#stream.write(`
|
|
1870
|
+
`);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
#onBarDone() {
|
|
1874
|
+
this.#doneCount++;
|
|
1875
|
+
if (this.#doneCount >= this.#totalRows && this.#totalRows > 0) {
|
|
1876
|
+
this.#allDone = true;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
// node_modules/@puppeteer/browsers/lib/install.js
|
|
1882
|
+
var debugInstall = debug("puppeteer:browsers:install");
|
|
1883
|
+
var times = new Map;
|
|
1884
|
+
function debugTime(label) {
|
|
1885
|
+
times.set(label, process.hrtime());
|
|
1886
|
+
}
|
|
1887
|
+
function debugTimeEnd(label) {
|
|
1888
|
+
const end = process.hrtime();
|
|
1889
|
+
const start = times.get(label);
|
|
1890
|
+
if (!start) {
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
const duration = end[0] * 1000 + end[1] / 1e6 - (start[0] * 1000 + start[1] / 1e6);
|
|
1894
|
+
debugInstall?.(`Duration for ${label}: ${duration}ms`);
|
|
1895
|
+
}
|
|
1896
|
+
async function installWithProviders(options) {
|
|
1897
|
+
if (!options.platform) {
|
|
1898
|
+
throw new Error("Platform must be defined");
|
|
1899
|
+
}
|
|
1900
|
+
const cache = new Cache(options.cacheDir);
|
|
1901
|
+
const browserRoot = cache.browserRoot(options.browser);
|
|
1902
|
+
const providers = [...options.providers || []];
|
|
1903
|
+
if (options.baseUrl) {
|
|
1904
|
+
providers.push(new DefaultProvider(options.baseUrl));
|
|
1905
|
+
}
|
|
1906
|
+
if (!options.baseUrl || options.forceFallbackForTesting) {
|
|
1907
|
+
providers.push(new DefaultProvider);
|
|
1908
|
+
}
|
|
1909
|
+
const downloadOptions = {
|
|
1910
|
+
browser: options.browser,
|
|
1911
|
+
platform: options.platform,
|
|
1912
|
+
buildId: options.buildId,
|
|
1913
|
+
progressCallback: options.downloadProgressCallback === "default" ? await makeProgressCallback(options.browser, options.buildIdAlias ?? options.buildId) : options.downloadProgressCallback
|
|
1914
|
+
};
|
|
1915
|
+
const errors = [];
|
|
1916
|
+
for (const provider of providers) {
|
|
1917
|
+
try {
|
|
1918
|
+
if (!await provider.supports(downloadOptions)) {
|
|
1919
|
+
debugInstall?.(`Provider ${provider.getName()} does not support ${options.browser} on ${options.platform}`);
|
|
1920
|
+
continue;
|
|
1921
|
+
}
|
|
1922
|
+
if (!(provider instanceof DefaultProvider)) {
|
|
1923
|
+
debugInstall?.(`⚠️ Using custom downloader: ${provider.getName()}`);
|
|
1924
|
+
debugInstall?.(`⚠️ Puppeteer does not guarantee compatibility with non-default providers`);
|
|
1925
|
+
}
|
|
1926
|
+
debugInstall?.(`Trying provider: ${provider.getName()} for ${options.browser} ${options.buildId}`);
|
|
1927
|
+
const url = await provider.getDownloadUrl(downloadOptions);
|
|
1928
|
+
if (!url) {
|
|
1929
|
+
debugInstall?.(`Provider ${provider.getName()} returned no URL for ${options.browser} ${options.buildId}`);
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1932
|
+
debugInstall?.(`Successfully got URL from ${provider.getName()}: ${url}`);
|
|
1933
|
+
if (!existsSync(browserRoot)) {
|
|
1934
|
+
await mkdir2(browserRoot, { recursive: true });
|
|
1935
|
+
}
|
|
1936
|
+
return await installUrl(url, options, provider);
|
|
1937
|
+
} catch (err) {
|
|
1938
|
+
debugInstall?.(`Provider ${provider.getName()} failed: ${err.message}`);
|
|
1939
|
+
errors.push({
|
|
1940
|
+
providerName: provider.getName(),
|
|
1941
|
+
error: err
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
const errorDetails = errors.map((e) => {
|
|
1946
|
+
return ` - ${e.providerName}: ${e.error.message}`;
|
|
1947
|
+
}).join(`
|
|
1948
|
+
`);
|
|
1949
|
+
throw new Error(`All providers failed for ${options.browser} ${options.buildId}:
|
|
1950
|
+
${errorDetails}`);
|
|
1951
|
+
}
|
|
1952
|
+
async function install(options) {
|
|
1953
|
+
options.platform ??= detectBrowserPlatform();
|
|
1954
|
+
options.unpack ??= true;
|
|
1955
|
+
if (!options.platform) {
|
|
1956
|
+
throw new Error(`Cannot download a binary for the provided platform: ${os5.platform()} (${os5.arch()})`);
|
|
1957
|
+
}
|
|
1958
|
+
options.providers ??= [];
|
|
1959
|
+
return await installWithProviders(options);
|
|
1960
|
+
}
|
|
1961
|
+
async function installDeps(installedBrowser) {
|
|
1962
|
+
if (process.platform !== "linux" || installedBrowser.platform !== BrowserPlatform.LINUX) {
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
const depsPath = path8.join(path8.dirname(installedBrowser.executablePath), "deb.deps");
|
|
1966
|
+
if (!existsSync(depsPath)) {
|
|
1967
|
+
debugInstall?.(`deb.deps file was not found at ${depsPath}`);
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
const data = readFileSync(depsPath, "utf-8").split(`
|
|
1971
|
+
`).join(",");
|
|
1972
|
+
if (process.getuid?.() !== 0) {
|
|
1973
|
+
throw new Error("Installing system dependencies requires root privileges");
|
|
1974
|
+
}
|
|
1975
|
+
let result = spawnSync2("apt-get", ["-v"]);
|
|
1976
|
+
if (result.status !== 0) {
|
|
1977
|
+
throw new Error("Failed to install system dependencies: apt-get does not seem to be available");
|
|
1978
|
+
}
|
|
1979
|
+
debugInstall?.(`Trying to install dependencies: ${data}`);
|
|
1980
|
+
result = spawnSync2("apt-get", [
|
|
1981
|
+
"satisfy",
|
|
1982
|
+
"-y",
|
|
1983
|
+
data,
|
|
1984
|
+
"--no-install-recommends"
|
|
1985
|
+
]);
|
|
1986
|
+
if (result.status !== 0) {
|
|
1987
|
+
throw new Error(`Failed to install system dependencies: status=${result.status},error=${result.error},stdout=${result.stdout.toString("utf8")},stderr=${result.stderr.toString("utf8")}`);
|
|
1988
|
+
}
|
|
1989
|
+
debugInstall?.(`Installed system dependencies ${data}`);
|
|
1990
|
+
}
|
|
1991
|
+
async function installUrl(url, options, provider) {
|
|
1992
|
+
if (!provider) {
|
|
1993
|
+
throw new Error("Provider is required for installation");
|
|
1994
|
+
}
|
|
1995
|
+
options.platform ??= detectBrowserPlatform();
|
|
1996
|
+
if (!options.platform) {
|
|
1997
|
+
throw new Error(`Cannot download a binary for the provided platform: ${os5.platform()} (${os5.arch()})`);
|
|
1998
|
+
}
|
|
1999
|
+
let downloadProgressCallback = options.downloadProgressCallback;
|
|
2000
|
+
if (downloadProgressCallback === "default") {
|
|
2001
|
+
downloadProgressCallback = await makeProgressCallback(options.browser, options.buildIdAlias ?? options.buildId);
|
|
2002
|
+
}
|
|
2003
|
+
const fileName = decodeURIComponent(url.toString()).split("/").pop();
|
|
2004
|
+
assert(fileName, `A malformed download URL was found: ${url}.`);
|
|
2005
|
+
const cache = new Cache(options.cacheDir);
|
|
2006
|
+
const browserRoot = cache.browserRoot(options.browser);
|
|
2007
|
+
const archivePath = path8.join(browserRoot, `${options.buildId}-${fileName}`);
|
|
2008
|
+
if (!existsSync(browserRoot)) {
|
|
2009
|
+
await mkdir2(browserRoot, { recursive: true });
|
|
2010
|
+
}
|
|
2011
|
+
if (!options.unpack) {
|
|
2012
|
+
if (existsSync(archivePath)) {
|
|
2013
|
+
return archivePath;
|
|
2014
|
+
}
|
|
2015
|
+
debugInstall?.(`Downloading binary from ${url}`);
|
|
2016
|
+
debugTime("download");
|
|
2017
|
+
await downloadFile(url, archivePath, downloadProgressCallback);
|
|
2018
|
+
debugTimeEnd("download");
|
|
2019
|
+
return archivePath;
|
|
2020
|
+
}
|
|
2021
|
+
const outputPath = cache.installationDir(options.browser, options.platform, options.buildId);
|
|
2022
|
+
const relativeExecutablePath6 = await provider.getExecutablePath({
|
|
2023
|
+
browser: options.browser,
|
|
2024
|
+
buildId: options.buildId,
|
|
2025
|
+
platform: options.platform
|
|
2026
|
+
});
|
|
2027
|
+
debugInstall?.(`Using executable path from provider: ${relativeExecutablePath6}`);
|
|
2028
|
+
const installedBrowser = new InstalledBrowser(cache, options.browser, options.buildId, options.platform);
|
|
2029
|
+
if (!(provider instanceof DefaultProvider)) {
|
|
2030
|
+
cache.writeExecutablePath(options.browser, options.platform, options.buildId, relativeExecutablePath6);
|
|
2031
|
+
}
|
|
2032
|
+
try {
|
|
2033
|
+
if (existsSync(outputPath)) {
|
|
2034
|
+
if (!existsSync(installedBrowser.executablePath)) {
|
|
2035
|
+
throw new Error(`The browser folder (${outputPath}) exists but the executable (${installedBrowser.executablePath}) is missing`);
|
|
2036
|
+
}
|
|
2037
|
+
await runSetup(installedBrowser);
|
|
2038
|
+
if (options.installDeps) {
|
|
2039
|
+
await installDeps(installedBrowser);
|
|
2040
|
+
}
|
|
2041
|
+
return installedBrowser;
|
|
2042
|
+
}
|
|
2043
|
+
if (!existsSync(archivePath)) {
|
|
2044
|
+
debugInstall?.(`Downloading binary from ${url}`);
|
|
2045
|
+
try {
|
|
2046
|
+
debugTime("download");
|
|
2047
|
+
await downloadFile(url, archivePath, downloadProgressCallback);
|
|
2048
|
+
} finally {
|
|
2049
|
+
debugTimeEnd("download");
|
|
2050
|
+
}
|
|
2051
|
+
} else {
|
|
2052
|
+
debugInstall?.(`Using existing archive at ${archivePath}`);
|
|
2053
|
+
}
|
|
2054
|
+
debugInstall?.(`Installing ${archivePath} to ${outputPath}`);
|
|
2055
|
+
try {
|
|
2056
|
+
debugTime("extract");
|
|
2057
|
+
await unpackArchive(archivePath, outputPath);
|
|
2058
|
+
} finally {
|
|
2059
|
+
debugTimeEnd("extract");
|
|
2060
|
+
}
|
|
2061
|
+
if (options.buildIdAlias) {
|
|
2062
|
+
const metadata = installedBrowser.readMetadata();
|
|
2063
|
+
metadata.aliases[options.buildIdAlias] = options.buildId;
|
|
2064
|
+
installedBrowser.writeMetadata(metadata);
|
|
2065
|
+
}
|
|
2066
|
+
await runSetup(installedBrowser);
|
|
2067
|
+
if (options.installDeps) {
|
|
2068
|
+
await installDeps(installedBrowser);
|
|
2069
|
+
}
|
|
2070
|
+
return installedBrowser;
|
|
2071
|
+
} finally {
|
|
2072
|
+
if (existsSync(archivePath)) {
|
|
2073
|
+
await unlink(archivePath);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
async function runSetup(installedBrowser) {
|
|
2078
|
+
if ((installedBrowser.platform === BrowserPlatform.WIN32 || installedBrowser.platform === BrowserPlatform.WIN64) && installedBrowser.browser === Browser.CHROME && installedBrowser.platform === detectBrowserPlatform()) {
|
|
2079
|
+
try {
|
|
2080
|
+
debugTime("permissions");
|
|
2081
|
+
const browserDir = path8.dirname(installedBrowser.executablePath);
|
|
2082
|
+
const setupExePath = path8.join(browserDir, "setup.exe");
|
|
2083
|
+
if (!existsSync(setupExePath)) {
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
spawnSync2(path8.join(browserDir, "setup.exe"), [`--configure-browser-in-directory=` + browserDir], {
|
|
2087
|
+
shell: false
|
|
2088
|
+
});
|
|
2089
|
+
} finally {
|
|
2090
|
+
debugTimeEnd("permissions");
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
async function uninstall(options) {
|
|
2095
|
+
options.platform ??= detectBrowserPlatform();
|
|
2096
|
+
if (!options.platform) {
|
|
2097
|
+
throw new Error(`Cannot detect the browser platform for: ${os5.platform()} (${os5.arch()})`);
|
|
2098
|
+
}
|
|
2099
|
+
new Cache(options.cacheDir).uninstall(options.browser, options.platform, options.buildId);
|
|
2100
|
+
}
|
|
2101
|
+
async function getInstalledBrowsers(options) {
|
|
2102
|
+
return new Cache(options.cacheDir).getInstalledBrowsers();
|
|
2103
|
+
}
|
|
2104
|
+
async function canDownload(options) {
|
|
2105
|
+
options.platform ??= detectBrowserPlatform();
|
|
2106
|
+
if (!options.platform) {
|
|
2107
|
+
throw new Error(`Cannot download a binary for the provided platform: ${os5.platform()} (${os5.arch()})`);
|
|
2108
|
+
}
|
|
2109
|
+
const providers = [
|
|
2110
|
+
...options.providers || [],
|
|
2111
|
+
new DefaultProvider(options.baseUrl)
|
|
2112
|
+
];
|
|
2113
|
+
const downloadOptions = {
|
|
2114
|
+
browser: options.browser,
|
|
2115
|
+
platform: options.platform,
|
|
2116
|
+
buildId: options.buildId
|
|
2117
|
+
};
|
|
2118
|
+
for (const provider of providers) {
|
|
2119
|
+
if (!await provider.supports(downloadOptions)) {
|
|
2120
|
+
continue;
|
|
2121
|
+
}
|
|
2122
|
+
const url = await provider.getDownloadUrl(downloadOptions);
|
|
2123
|
+
if (url && await headHttpRequest(url)) {
|
|
2124
|
+
return true;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
return false;
|
|
2128
|
+
}
|
|
2129
|
+
function getDownloadUrl(browser, platform, buildId, baseUrl) {
|
|
2130
|
+
return new URL(downloadUrls[browser](platform, buildId, baseUrl));
|
|
2131
|
+
}
|
|
2132
|
+
async function makeProgressCallback(browser, buildId) {
|
|
2133
|
+
let ticker;
|
|
2134
|
+
let lastDownloadedBytes = 0;
|
|
2135
|
+
return (downloadedBytes, totalBytes) => {
|
|
2136
|
+
if (!ticker) {
|
|
2137
|
+
ticker = ProgressBar.createBarTicker(`Downloading ${browser} ${buildId} - ${toMegabytes(totalBytes)}`, totalBytes);
|
|
2138
|
+
}
|
|
2139
|
+
const delta = downloadedBytes - lastDownloadedBytes;
|
|
2140
|
+
lastDownloadedBytes = downloadedBytes;
|
|
2141
|
+
ticker(delta);
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
function toMegabytes(bytes) {
|
|
2145
|
+
const mb = bytes / 1000 / 1000;
|
|
2146
|
+
return `${Math.round(mb * 10) / 10} MB`;
|
|
2147
|
+
}
|
|
2148
|
+
// node_modules/@puppeteer/browsers/lib/CLI.js
|
|
2149
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
2150
|
+
import fs3 from "node:fs";
|
|
2151
|
+
import os6 from "node:os";
|
|
2152
|
+
import path9 from "node:path";
|
|
2153
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
2154
|
+
import * as readline2 from "node:readline";
|
|
2155
|
+
function isValidBrowser(browser) {
|
|
2156
|
+
return Object.values(Browser).includes(browser);
|
|
2157
|
+
}
|
|
2158
|
+
function isValidPlatform(platform) {
|
|
2159
|
+
return Object.values(BrowserPlatform).includes(platform);
|
|
2160
|
+
}
|
|
2161
|
+
var packageVersion = "3.0.4";
|
|
2162
|
+
|
|
2163
|
+
class CLI {
|
|
2164
|
+
#cachePath;
|
|
2165
|
+
#rl;
|
|
2166
|
+
#scriptName;
|
|
2167
|
+
#version;
|
|
2168
|
+
#allowCachePathOverride;
|
|
2169
|
+
#pinnedBrowsers;
|
|
2170
|
+
#prefixCommand;
|
|
2171
|
+
constructor(opts, rl) {
|
|
2172
|
+
if (!opts) {
|
|
2173
|
+
opts = {};
|
|
2174
|
+
}
|
|
2175
|
+
if (typeof opts === "string") {
|
|
2176
|
+
opts = {
|
|
2177
|
+
cachePath: opts
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
this.#cachePath = opts.cachePath ?? process.cwd();
|
|
2181
|
+
this.#rl = rl;
|
|
2182
|
+
this.#scriptName = opts.scriptName ?? "@puppeteer/browsers";
|
|
2183
|
+
this.#version = opts.version ?? packageVersion;
|
|
2184
|
+
this.#allowCachePathOverride = opts.allowCachePathOverride ?? true;
|
|
2185
|
+
this.#pinnedBrowsers = opts.pinnedBrowsers;
|
|
2186
|
+
this.#prefixCommand = opts.prefixCommand;
|
|
2187
|
+
}
|
|
2188
|
+
#defineBrowserParameter(yargs, required) {
|
|
2189
|
+
return yargs.positional("browser", {
|
|
2190
|
+
description: "Which browser to install <browser>[@<buildId|latest>]. `latest` will try to find the latest available build. `buildId` is a browser-specific identifier such as a version or a revision.",
|
|
2191
|
+
type: "string",
|
|
2192
|
+
coerce: (opt) => {
|
|
2193
|
+
const browser = {
|
|
2194
|
+
name: this.#parseBrowser(opt),
|
|
2195
|
+
buildId: this.#parseBuildId(opt)
|
|
2196
|
+
};
|
|
2197
|
+
if (!isValidBrowser(browser.name)) {
|
|
2198
|
+
throw new Error(`Unsupported browser '${browser.name}'`);
|
|
2199
|
+
}
|
|
2200
|
+
return browser;
|
|
2201
|
+
},
|
|
2202
|
+
demandOption: required
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
#definePlatformParameter(yargs) {
|
|
2206
|
+
return yargs.option("platform", {
|
|
2207
|
+
type: "string",
|
|
2208
|
+
desc: "Platform that the binary needs to be compatible with.",
|
|
2209
|
+
choices: Object.values(BrowserPlatform),
|
|
2210
|
+
default: detectBrowserPlatform(),
|
|
2211
|
+
coerce: (platform) => {
|
|
2212
|
+
if (!isValidPlatform(platform)) {
|
|
2213
|
+
throw new Error(`Unsupported platform '${platform}'`);
|
|
2214
|
+
}
|
|
2215
|
+
return platform;
|
|
2216
|
+
},
|
|
2217
|
+
defaultDescription: "Auto-detected"
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
#definePathParameter(yargs, required = false) {
|
|
2221
|
+
if (!this.#allowCachePathOverride) {
|
|
2222
|
+
return yargs;
|
|
2223
|
+
}
|
|
2224
|
+
return yargs.option("path", {
|
|
2225
|
+
type: "string",
|
|
2226
|
+
desc: "Path to the root folder for the browser downloads and installation. If a relative path is provided, it will be resolved relative to the current working directory. The installation folder structure is compatible with the cache structure used by Puppeteer.",
|
|
2227
|
+
defaultDescription: "Current working directory",
|
|
2228
|
+
...required ? {} : { default: process.cwd() },
|
|
2229
|
+
demandOption: required
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
async run(argv) {
|
|
2233
|
+
const { default: yargs } = await import("./index-4706p1xh.mjs");
|
|
2234
|
+
const { hideBin } = await import("./helpers-667kxskd.mjs");
|
|
2235
|
+
const yargsInstance = yargs(hideBin(argv));
|
|
2236
|
+
let target = yargsInstance.scriptName(this.#scriptName).version(this.#version);
|
|
2237
|
+
if (this.#prefixCommand) {
|
|
2238
|
+
target = target.command(this.#prefixCommand.cmd, this.#prefixCommand.description, (yargs2) => {
|
|
2239
|
+
return this.#build(yargs2);
|
|
2240
|
+
});
|
|
2241
|
+
} else {
|
|
2242
|
+
target = this.#build(target);
|
|
2243
|
+
}
|
|
2244
|
+
await target.demandCommand(1).help().wrap(Math.min(120, yargsInstance.terminalWidth())).parseAsync();
|
|
2245
|
+
}
|
|
2246
|
+
#build(yargs) {
|
|
2247
|
+
const latestOrPinned = this.#pinnedBrowsers ? "pinned" : "latest";
|
|
2248
|
+
const browserArgType = this.#pinnedBrowsers ? "[browser]" : "<browser>";
|
|
2249
|
+
return yargs.command(`install ${browserArgType}`, "Download and install the specified browser. If successful, the command outputs the actual browser buildId that was installed and the absolute path to the browser executable (see --format).", (yargs2) => {
|
|
2250
|
+
if (this.#pinnedBrowsers) {
|
|
2251
|
+
yargs2.example("$0 install", "Install all pinned browsers");
|
|
2252
|
+
}
|
|
2253
|
+
yargs2.example("$0 install chrome", `Install the ${latestOrPinned} available build of the Chrome browser.`).example("$0 install chrome@latest", "Install the latest available build for the Chrome browser.").example("$0 install chrome@stable", "Install the latest available build for the Chrome browser from the stable channel.").example("$0 install chrome@beta", "Install the latest available build for the Chrome browser from the beta channel.").example("$0 install chrome@dev", "Install the latest available build for the Chrome browser from the dev channel.").example("$0 install chrome@canary", "Install the latest available build for the Chrome Canary browser.").example("$0 install chrome@115", "Install the latest available build for Chrome 115.").example("$0 install chromedriver@canary", "Install the latest available build for ChromeDriver Canary.").example("$0 install chromedriver@115", "Install the latest available build for ChromeDriver 115.").example("$0 install chromedriver@115.0.5790", "Install the latest available patch (115.0.5790.X) build for ChromeDriver.").example("$0 install chrome-headless-shell", "Install the latest available chrome-headless-shell build.").example("$0 install chrome-headless-shell@beta", "Install the latest available chrome-headless-shell build corresponding to the Beta channel.").example("$0 install chrome-headless-shell@118", "Install the latest available chrome-headless-shell 118 build.").example("$0 install chromium@1083080", "Install the revision 1083080 of the Chromium browser.").example("$0 install firefox", "Install the latest nightly available build of the Firefox browser.").example("$0 install firefox@stable", "Install the latest stable build of the Firefox browser.").example("$0 install firefox@beta", "Install the latest beta build of the Firefox browser.").example("$0 install firefox@devedition", "Install the latest devedition build of the Firefox browser.").example("$0 install firefox@esr", "Install the latest ESR build of the Firefox browser.").example("$0 install firefox@nightly", "Install the latest nightly build of the Firefox browser.").example("$0 install firefox@stable_111.0.1", "Install a specific version of the Firefox browser.").example("$0 install firefox --platform mac", "Install the latest Mac (Intel) build of the Firefox browser.");
|
|
2254
|
+
if (this.#allowCachePathOverride) {
|
|
2255
|
+
yargs2.example("$0 install firefox --path /tmp/my-browser-cache", "Install to the specified cache directory.");
|
|
2256
|
+
}
|
|
2257
|
+
const yargsWithBrowserParam = this.#defineBrowserParameter(yargs2, !Boolean(this.#pinnedBrowsers));
|
|
2258
|
+
const yargsWithPlatformParam = this.#definePlatformParameter(yargsWithBrowserParam);
|
|
2259
|
+
return this.#definePathParameter(yargsWithPlatformParam, false).option("base-url", {
|
|
2260
|
+
type: "string",
|
|
2261
|
+
desc: "Base URL to download from"
|
|
2262
|
+
}).option("install-deps", {
|
|
2263
|
+
type: "boolean",
|
|
2264
|
+
desc: "Whether to attempt installing system dependencies (only supported on Linux, requires root privileges).",
|
|
2265
|
+
default: false
|
|
2266
|
+
}).option("format", {
|
|
2267
|
+
type: "string",
|
|
2268
|
+
desc: "Format to use for the output. Supported placeholders: {{browser}}, {{buildId}}, {{path}}, {{platform}}",
|
|
2269
|
+
default: "{{browser}}@{{buildId}} {{path}}"
|
|
2270
|
+
});
|
|
2271
|
+
}, async (args) => {
|
|
2272
|
+
if (this.#pinnedBrowsers && !args.browser) {
|
|
2273
|
+
const result = await Promise.allSettled(Object.entries(this.#pinnedBrowsers).map(async ([browser, options]) => {
|
|
2274
|
+
if (options.skipDownload) {
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
await this.#install({
|
|
2278
|
+
...args,
|
|
2279
|
+
browser: {
|
|
2280
|
+
name: browser,
|
|
2281
|
+
buildId: options.buildId
|
|
2282
|
+
}
|
|
2283
|
+
});
|
|
2284
|
+
}));
|
|
2285
|
+
for (const install2 of result) {
|
|
2286
|
+
if (install2.status === "rejected") {
|
|
2287
|
+
throw install2.reason;
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
} else {
|
|
2291
|
+
await this.#install(args);
|
|
2292
|
+
}
|
|
2293
|
+
}).command("launch <browser>", "Launch the specified browser", (yargs2) => {
|
|
2294
|
+
yargs2.example("$0 launch chrome@115.0.5790.170", "Launch Chrome 115.0.5790.170").example("$0 launch firefox@112.0a1", "Launch the Firefox browser identified by the milestone 112.0a1.").example("$0 launch chrome@115.0.5790.170 --detached", "Launch the browser but detach the sub-processes.").example("$0 launch chrome@canary --system", "Try to locate the Canary build of Chrome installed on the system and launch it.").example("$0 launch chrome@115.0.5790.170 -- --version", "Launch Chrome 115.0.5790.170 and pass custom argument to the binary.");
|
|
2295
|
+
const yargsWithExtraAgs = yargs2.parserConfiguration({
|
|
2296
|
+
"populate--": true
|
|
2297
|
+
});
|
|
2298
|
+
const yargsWithBrowserParam = this.#defineBrowserParameter(yargsWithExtraAgs, true);
|
|
2299
|
+
const yargsWithPlatformParam = this.#definePlatformParameter(yargsWithBrowserParam);
|
|
2300
|
+
return this.#definePathParameter(yargsWithPlatformParam).option("detached", {
|
|
2301
|
+
type: "boolean",
|
|
2302
|
+
desc: "Detach the child process.",
|
|
2303
|
+
default: false
|
|
2304
|
+
}).option("system", {
|
|
2305
|
+
type: "boolean",
|
|
2306
|
+
desc: "Search for a browser installed on the system instead of the cache folder.",
|
|
2307
|
+
default: false
|
|
2308
|
+
}).option("dumpio", {
|
|
2309
|
+
type: "boolean",
|
|
2310
|
+
desc: "Forwards the browser's process stdout and stderr",
|
|
2311
|
+
default: false
|
|
2312
|
+
});
|
|
2313
|
+
}, async (args) => {
|
|
2314
|
+
const extraArgs = args["--"]?.filter((arg) => {
|
|
2315
|
+
return typeof arg === "string";
|
|
2316
|
+
});
|
|
2317
|
+
args.browser.buildId = this.#resolvePinnedBrowserIfNeeded(args.browser.buildId, args.browser.name);
|
|
2318
|
+
const executablePath = args.system ? computeSystemExecutablePath({
|
|
2319
|
+
browser: args.browser.name,
|
|
2320
|
+
channel: args.browser.buildId,
|
|
2321
|
+
platform: args.platform
|
|
2322
|
+
}) : computeExecutablePath({
|
|
2323
|
+
browser: args.browser.name,
|
|
2324
|
+
buildId: args.browser.buildId,
|
|
2325
|
+
cacheDir: args.path ?? this.#cachePath,
|
|
2326
|
+
platform: args.platform
|
|
2327
|
+
});
|
|
2328
|
+
launch({
|
|
2329
|
+
args: extraArgs,
|
|
2330
|
+
executablePath,
|
|
2331
|
+
dumpio: args.dumpio,
|
|
2332
|
+
detached: args.detached
|
|
2333
|
+
});
|
|
2334
|
+
}).command("clear", this.#allowCachePathOverride ? "Removes all installed browsers from the specified cache directory" : `Removes all installed browsers from ${this.#cachePath}`, (yargs2) => {
|
|
2335
|
+
return this.#definePathParameter(yargs2, true);
|
|
2336
|
+
}, async (args) => {
|
|
2337
|
+
const cacheDir = args.path ?? this.#cachePath;
|
|
2338
|
+
const rl = this.#rl ?? readline2.createInterface({ input, output });
|
|
2339
|
+
rl.question(`Do you want to permanently and recursively delete the content of ${cacheDir} (yes/No)? `, (answer) => {
|
|
2340
|
+
rl.close();
|
|
2341
|
+
if (!["y", "yes"].includes(answer.toLowerCase().trim())) {
|
|
2342
|
+
console.log("Cancelled.");
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
const cache = new Cache(cacheDir);
|
|
2346
|
+
cache.clear();
|
|
2347
|
+
console.log(`${cacheDir} cleared.`);
|
|
2348
|
+
});
|
|
2349
|
+
}).command("list", "List all installed browsers in the cache directory", (yargs2) => {
|
|
2350
|
+
yargs2.example("$0 list", "List all installed browsers in the cache directory");
|
|
2351
|
+
if (this.#allowCachePathOverride) {
|
|
2352
|
+
yargs2.example("$0 list --path /tmp/my-browser-cache", "List browsers installed in the specified cache directory");
|
|
2353
|
+
}
|
|
2354
|
+
return this.#definePathParameter(yargs2);
|
|
2355
|
+
}, async (args) => {
|
|
2356
|
+
const cacheDir = args.path ?? this.#cachePath;
|
|
2357
|
+
const cache = new Cache(cacheDir);
|
|
2358
|
+
const browsers = cache.getInstalledBrowsers();
|
|
2359
|
+
for (const browser of browsers) {
|
|
2360
|
+
console.log(`${browser.browser}@${browser.buildId} (${browser.platform}) ${browser.executablePath}`);
|
|
2361
|
+
}
|
|
2362
|
+
}).command("bisect <path>", "(experimental) Bisect Chrome for Testing using the specified script. Downloads https://chromium.googlesource.com/chromium/src.git/+/main/tools/bisect-builds.py to ~/bisect-builds.py if needed.", (yargs2) => {
|
|
2363
|
+
return yargs2.positional("path", {
|
|
2364
|
+
type: "string",
|
|
2365
|
+
description: "Path to a script or test name to bisect.",
|
|
2366
|
+
demandOption: true
|
|
2367
|
+
}).option("good", {
|
|
2368
|
+
type: "string",
|
|
2369
|
+
alias: "g",
|
|
2370
|
+
demandOption: true,
|
|
2371
|
+
desc: "Last known good version"
|
|
2372
|
+
}).option("bad", {
|
|
2373
|
+
type: "string",
|
|
2374
|
+
alias: "b",
|
|
2375
|
+
demandOption: true,
|
|
2376
|
+
desc: "First known bad version"
|
|
2377
|
+
}).option("cft", {
|
|
2378
|
+
type: "boolean",
|
|
2379
|
+
desc: "Use -cft",
|
|
2380
|
+
default: true
|
|
2381
|
+
});
|
|
2382
|
+
}, async (args) => {
|
|
2383
|
+
const isScript = args.path.endsWith(".mjs") || args.path.endsWith(".cjs") || args.path.endsWith(".js");
|
|
2384
|
+
const testCommand = isScript ? `PUPPETEER_EXECUTABLE_PATH=%p node ${args.path}` : `BINARY=%p npm run ${args.path}`;
|
|
2385
|
+
const bisectScriptPath = path9.join(os6.homedir(), "bisect-builds.py");
|
|
2386
|
+
if (!fs3.existsSync(bisectScriptPath)) {
|
|
2387
|
+
console.log("Downloading bisect-builds.py...");
|
|
2388
|
+
const response = await fetch("https://chromium.googlesource.com/chromium/src.git/+/main/tools/bisect-builds.py?format=TEXT");
|
|
2389
|
+
if (!response.ok) {
|
|
2390
|
+
throw new Error(`Failed to download bisect-builds.py: ${response.statusText}`);
|
|
2391
|
+
}
|
|
2392
|
+
const base64Text = await response.text();
|
|
2393
|
+
const decodedText = Buffer.from(base64Text, "base64").toString("utf-8");
|
|
2394
|
+
fs3.writeFileSync(bisectScriptPath, decodedText, { mode: 493 });
|
|
2395
|
+
console.log(`Saved bisect-builds.py to ${bisectScriptPath}`);
|
|
2396
|
+
}
|
|
2397
|
+
const pythonExecutable = "python3";
|
|
2398
|
+
const bisectArgs = [
|
|
2399
|
+
bisectScriptPath,
|
|
2400
|
+
"-g",
|
|
2401
|
+
args.good,
|
|
2402
|
+
"-b",
|
|
2403
|
+
args.bad,
|
|
2404
|
+
args.cft ? "-cft" : "-s",
|
|
2405
|
+
"-v",
|
|
2406
|
+
"--verify-range",
|
|
2407
|
+
"--not-interactive",
|
|
2408
|
+
"-c",
|
|
2409
|
+
testCommand
|
|
2410
|
+
];
|
|
2411
|
+
await new Promise((resolve2, reject) => {
|
|
2412
|
+
const createProcess = spawn2(pythonExecutable, bisectArgs, {
|
|
2413
|
+
stdio: "inherit"
|
|
2414
|
+
});
|
|
2415
|
+
createProcess.on("error", (message) => {
|
|
2416
|
+
reject(message);
|
|
2417
|
+
});
|
|
2418
|
+
createProcess.on("exit", (code) => {
|
|
2419
|
+
if (code !== 0) {
|
|
2420
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
2421
|
+
} else {
|
|
2422
|
+
resolve2();
|
|
2423
|
+
}
|
|
2424
|
+
});
|
|
2425
|
+
});
|
|
2426
|
+
}).demandCommand(1).help();
|
|
2427
|
+
}
|
|
2428
|
+
#parseBrowser(version) {
|
|
2429
|
+
return version.split("@").shift();
|
|
2430
|
+
}
|
|
2431
|
+
#parseBuildId(version) {
|
|
2432
|
+
const parts = version.split("@");
|
|
2433
|
+
return parts.length === 2 ? parts[1] : this.#pinnedBrowsers ? "pinned" : "latest";
|
|
2434
|
+
}
|
|
2435
|
+
#resolvePinnedBrowserIfNeeded(buildId, browserName) {
|
|
2436
|
+
if (buildId === "pinned") {
|
|
2437
|
+
const options = this.#pinnedBrowsers?.[browserName];
|
|
2438
|
+
if (!options || !options.buildId) {
|
|
2439
|
+
throw new Error(`No pinned version found for ${browserName}`);
|
|
2440
|
+
}
|
|
2441
|
+
return options.buildId;
|
|
2442
|
+
}
|
|
2443
|
+
return buildId;
|
|
2444
|
+
}
|
|
2445
|
+
async#install(args) {
|
|
2446
|
+
if (!args.browser) {
|
|
2447
|
+
throw new Error(`No browser arg provided`);
|
|
2448
|
+
}
|
|
2449
|
+
if (!args.platform) {
|
|
2450
|
+
throw new Error(`Could not resolve the current platform`);
|
|
2451
|
+
}
|
|
2452
|
+
args.browser.buildId = this.#resolvePinnedBrowserIfNeeded(args.browser.buildId, args.browser.name);
|
|
2453
|
+
const originalBuildId = args.browser.buildId;
|
|
2454
|
+
args.browser.buildId = await resolveBuildId4(args.browser.name, args.platform, args.browser.buildId);
|
|
2455
|
+
await install({
|
|
2456
|
+
browser: args.browser.name,
|
|
2457
|
+
buildId: args.browser.buildId,
|
|
2458
|
+
platform: args.platform,
|
|
2459
|
+
cacheDir: args.path ?? this.#cachePath,
|
|
2460
|
+
downloadProgressCallback: "default",
|
|
2461
|
+
baseUrl: args.baseUrl,
|
|
2462
|
+
buildIdAlias: originalBuildId !== args.browser.buildId ? originalBuildId : undefined,
|
|
2463
|
+
installDeps: args.installDeps
|
|
2464
|
+
});
|
|
2465
|
+
const executablePath = computeExecutablePath({
|
|
2466
|
+
browser: args.browser.name,
|
|
2467
|
+
buildId: args.browser.buildId,
|
|
2468
|
+
cacheDir: args.path ?? this.#cachePath,
|
|
2469
|
+
platform: args.platform
|
|
2470
|
+
});
|
|
2471
|
+
console.log(args.format.replace(/{{browser}}/g, args.browser.name).replace(/{{buildId}}/g, args.browser.buildId).replace(/{{path}}/g, executablePath).replace(/{{platform}}/g, args.platform));
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
// node_modules/@puppeteer/browsers/lib/provider.js
|
|
2475
|
+
function buildArchiveFilename(browser, platform, buildId, extension = "zip") {
|
|
2476
|
+
return `${browser}-${platform}-${buildId}.${extension}`;
|
|
2477
|
+
}
|
|
2478
|
+
export { Browser, BrowserPlatform, BrowserTag, ChromeReleaseChannel, resolveBuildId4 as resolveBuildId, createProfile2 as createProfile, resolveDefaultUserDataDir2 as resolveDefaultUserDataDir, getVersionComparator, detectBrowserPlatform, InstalledBrowser, Cache, computeExecutablePath, computeSystemExecutablePath, launch, CDP_WEBSOCKET_ENDPOINT_REGEX, WEBDRIVER_BIDI_WEBSOCKET_ENDPOINT_REGEX, Process, TimeoutError, DefaultProvider, install, uninstall, getInstalledBrowsers, canDownload, getDownloadUrl, CLI, buildArchiveFilename };
|