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