fix: update vulnerable dependencies and adapt browser QA to Puppeteer 25

This commit is contained in:
Sameh Khamis committed 2026-09-10 23:08:26 -07:00
1 parent a458d27067
commit f94bdb1d77
33 files changed
+403 -1315

No files matched your search

+4
View File
@@ -50,6 +50,10 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
stale-data fallback. Concurrent identical requests share the same last-good stale-data fallback. Concurrent identical requests share the same last-good
fallback when all mirrors refuse, without duplicating upstream requests. fallback when all mirrors refuse, without duplicating upstream requests.
- Refresh vulnerable transitive dependencies and update browser/image tooling
to Puppeteer 25.10.0 and Sharp 0.35.4. Cesium remains on 1.138.0.
Browser QA awaits the new asynchronous executable-path lookup.
## [0.1.1] — 2026-09-01 — Installation and live-data fixes ## [0.1.1] — 2026-09-01 — Installation and live-data fixes
### Changed ### Changed
+8
View File
@@ -2642,3 +2642,11 @@ Replay transport uses one Play/Pause toggle plus Cancel. During ascent only the
## Maintenance Rule ## Maintenance Rule
When runtime behavior or architecture changes, update this file in the same change set as code updates. When runtime behavior or architecture changes, update this file in the same change set as code updates.
## Dependency security baseline
The lockfile uses DOMPurify 3.4.15, protobufjs 8.8.0, PostCSS 8.5.28, and
nanoid 3.3.19. Cesium remains on 1.138.0. Browser QA uses Puppeteer 25.10.0;
image-processing tools use Sharp 0.35.4. QA scripts await Puppeteer's asynchronous
executable-path lookup before testing or passing the path to Chrome. Supported Node versions remain
24.14.x and 26.x. Use `npm ci` to reproduce the checked-in dependency tree.
+360 -1284
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -51,8 +51,8 @@
"satellite.js": "^6.0.2" "satellite.js": "^6.0.2"
}, },
"devDependencies": { "devDependencies": {
"puppeteer": "^24.37.5", "puppeteer": "^25.10.0",
"sharp": "^0.34.5", "sharp": "^0.35.4",
"vite": "^6.0.0", "vite": "^6.0.0",
"vite-plugin-cesium": "^1.2.23", "vite-plugin-cesium": "^1.2.23",
"ws": "^8.21.0" "ws": "^8.21.0"
+1 -1
View File
@@ -34,7 +34,7 @@ mkdirSync(SHOT_DIR, { recursive: true });
const CHROME_EXECUTABLE_CANDIDATES = [ const CHROME_EXECUTABLE_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -106,7 +106,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -139,7 +139,7 @@ const CHROME_CANDIDATES = [
// Version-pinned Chrome-for-Testing over the auto-updating system Chrome: // Version-pinned Chrome-for-Testing over the auto-updating system Chrome:
// its software-GL behavior shifts across majors and has produced false // its software-GL behavior shifts across majors and has produced false
// negatives in this repo's harnesses before. // negatives in this repo's harnesses before.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
].filter(Boolean); ].filter(Boolean);
+1 -1
View File
@@ -13,7 +13,7 @@ fs.mkdirSync(shotsDir, { recursive: true });
const chromeCandidates = [ const chromeCandidates = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
].filter(Boolean); ].filter(Boolean);
const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate)); const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate));
+1 -1
View File
@@ -93,7 +93,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -70,7 +70,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -52,7 +52,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -38,7 +38,7 @@ const SHOT_DIR = path.join(ROOT, 'qa-shots', 'firstrun');
const CHROME_CANDIDATES = [ const CHROME_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
// Version-pinned Chrome-for-Testing over the auto-updating system Chrome. // Version-pinned Chrome-for-Testing over the auto-updating system Chrome.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
].filter(Boolean); ].filter(Boolean);
+1 -1
View File
@@ -56,7 +56,7 @@ function record(name, ok, detail) {
} }
fs.mkdirSync(OUT_DIR, { recursive: true }); fs.mkdirSync(OUT_DIR, { recursive: true });
const chrome = (() => { try { return puppeteer.executablePath(); } catch { return undefined; } })(); const chrome = await puppeteer.executablePath().catch(() => undefined);
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
headless: HEADFUL ? false : 'new', headless: HEADFUL ? false : 'new',
executablePath: chrome, executablePath: chrome,
+1 -1
View File
@@ -26,7 +26,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// across majors. // across majors.
const chrome = [ const chrome = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
].filter(Boolean).find((p) => fs.existsSync(p)); ].filter(Boolean).find((p) => fs.existsSync(p));
+1 -1
View File
@@ -27,7 +27,7 @@ const SHOT_EVERY_MS = Number(getOpt('--shot-ms', '2000'));
const CHROME_CANDIDATES = [ const CHROME_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
].filter(Boolean); ].filter(Boolean);
const CHROME_EXECUTABLE = CHROME_CANDIDATES.find((c) => { try { return fs.existsSync(c); } catch { return false; } }); const CHROME_EXECUTABLE = CHROME_CANDIDATES.find((c) => { try { return fs.existsSync(c); } catch { return false; } });
+1 -1
View File
@@ -123,7 +123,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -115,7 +115,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -1205,7 +1205,7 @@ async function runBrowserGroup(record) {
const emit = (id, res, ms) => { if (ids.includes(id)) record(CHECKS.find((c) => c.id === id), res, ms); }; const emit = (id, res, ms) => { if (ids.includes(id)) record(CHECKS.find((c) => c.id === id), res, ms); };
const only = (id) => ids.includes(id); const only = (id) => ids.includes(id);
const exe = (() => { try { return puppeteer.executablePath(); } catch { return null; } })(); const exe = await puppeteer.executablePath().catch(() => null);
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
headless: HEADFUL ? false : 'new', headless: HEADFUL ? false : 'new',
...(exe ? { executablePath: exe } : {}), ...(exe ? { executablePath: exe } : {}),
+1 -1
View File
@@ -157,7 +157,7 @@ const CHROME_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
// Pin puppeteer's Chrome-for-Testing: system Chrome auto-updates underneath // Pin puppeteer's Chrome-for-Testing: system Chrome auto-updates underneath
// the harnesses and its software-GL behaviour shifts across majors. // the harnesses and its software-GL behaviour shifts across majors.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
].filter(Boolean); ].filter(Boolean);
function findChrome() { function findChrome() {
+1 -1
View File
@@ -56,7 +56,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -19,7 +19,7 @@ const headful = process.argv.includes('--headful');
const forceKeyless = process.argv.includes('--keyless') const forceKeyless = process.argv.includes('--keyless')
|| process.env.QA_MAP_SOURCE_TRAY_KEYLESS === '1'; || process.env.QA_MAP_SOURCE_TRAY_KEYLESS === '1';
const executablePath = process.env.PUPPETEER_EXECUTABLE_PATH const executablePath = process.env.PUPPETEER_EXECUTABLE_PATH
|| (() => { try { return puppeteer.executablePath(); } catch { return null; } })(); || await puppeteer.executablePath().catch(() => null);
if (!executablePath || !fs.existsSync(executablePath)) { if (!executablePath || !fs.existsSync(executablePath)) {
throw new Error('Puppeteer Chrome for Testing is unavailable'); throw new Error('Puppeteer Chrome for Testing is unavailable');
+1 -1
View File
@@ -29,7 +29,7 @@ const HEADFUL = args.includes('--headful');
const chromeCandidates = [ const chromeCandidates = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
].filter(Boolean); ].filter(Boolean);
+1 -1
View File
@@ -70,7 +70,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -55,7 +55,7 @@ const DEGRADED_DELAY_MS = Math.max(0, getNumberOpt('--degraded-delay-ms', 2500))
const CHROME_EXECUTABLE_CANDIDATES = [ const CHROME_EXECUTABLE_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -61,7 +61,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -77,7 +77,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -53,7 +53,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -184,7 +184,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -61,7 +61,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
+1 -1
View File
@@ -32,7 +32,7 @@ fs.mkdirSync(shotsDir, { recursive: true });
const chromeCandidates = [ const chromeCandidates = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
].filter(Boolean); ].filter(Boolean);
const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate)); const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate));
+1 -1
View File
@@ -39,7 +39,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..'); const ROOT = path.resolve(__dirname, '..');
const CHROME_CANDIDATES = [ const CHROME_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH, process.env.PUPPETEER_EXECUTABLE_PATH,
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',
].filter(Boolean); ].filter(Boolean);
+1 -1
View File
@@ -30,7 +30,7 @@ if (fixtureSha256 !== expectedFixtureSha256) {
const appOrigin = new URL(appUrl).origin; const appOrigin = new URL(appUrl).origin;
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
headless: 'new', headless: 'new',
executablePath: puppeteer.executablePath(), executablePath: await puppeteer.executablePath(),
args: [ args: [
'--no-sandbox', '--no-sandbox',
'--disable-setuid-sandbox', '--disable-setuid-sandbox',
+1 -1
View File
@@ -118,7 +118,7 @@ const CHROME_EXECUTABLE_CANDIDATES = [
// tile-gated drain budget under SwiftShader on 2026-07-30 — six // tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic // false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses. // pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(), await puppeteer.executablePath().catch(() => null),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Chromium.app/Contents/MacOS/Chromium',