Skip to content

Commit 55b75f9

Browse files
authored
Handle errors when browser launching fails (#78)
1 parent 98ee520 commit 55b75f9

3 files changed

Lines changed: 66 additions & 45 deletions

File tree

.changeset/wicked-pumpkins-join.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'pleasantest': patch
3+
---
4+
5+
Handle errors thrown by browser launcher instead of silently hanging

src/connect-to-browser.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,24 @@ export const connectToBrowser = async (
121121
detached: true,
122122
stdio: 'ignore',
123123
});
124-
const wsEndpoint = await new Promise<string>((resolve) => {
124+
const wsEndpoint = await new Promise<string>((resolve, reject) => {
125125
subprocess.send({ browser, headless });
126126
subprocess.on('message', (msg: any) => {
127+
if (msg.error)
128+
return reject(new Error(`Failed to start browser: ${msg.error}`));
127129
if (!msg.browserWSEndpoint) return;
128130
resolve(msg.browserWSEndpoint);
129131
});
132+
}).catch(async (error) => {
133+
subprocess.kill();
134+
valueWrittenInMeantime = await updateConfig(
135+
configPath,
136+
browser,
137+
headless,
138+
'',
139+
'starting',
140+
);
141+
throw error;
130142
});
131143
valueWrittenInMeantime = await updateConfig(
132144
configPath,

src/start-disowned-browser.ts

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,56 @@ import { promises as fs } from 'fs';
44
import puppeteer from 'puppeteer';
55

66
process.on('message', async ({ browser, headless }) => {
7-
if (browser !== 'chromium')
8-
throw new Error(`unrecognized browser: ${browser}`);
9-
if (typeof headless !== 'boolean')
10-
throw new Error('headless must be a boolean');
7+
try {
8+
if (browser !== 'chromium')
9+
throw new Error(`unrecognized browser: ${browser}`);
10+
if (typeof headless !== 'boolean')
11+
throw new Error('headless must be a boolean');
1112

12-
let userDataDir: string | undefined;
13-
if (browser === 'chromium') {
14-
userDataDir = await fs.mkdtemp(os.tmpdir() + path.sep);
15-
const prefs = JSON.stringify({
16-
devtools: {
17-
preferences: {
18-
'panel-selectedTab': JSON.stringify('console'),
19-
currentDockState: JSON.stringify('right'),
20-
'InspectorView.splitViewState': JSON.stringify({
21-
horizontal: { size: 600 },
22-
vertical: { size: 450 },
23-
}),
13+
let userDataDir: string | undefined;
14+
if (browser === 'chromium') {
15+
userDataDir = await fs.mkdtemp(os.tmpdir() + path.sep);
16+
const prefs = JSON.stringify({
17+
devtools: {
18+
preferences: {
19+
'panel-selectedTab': JSON.stringify('console'),
20+
currentDockState: JSON.stringify('right'),
21+
'InspectorView.splitViewState': JSON.stringify({
22+
horizontal: { size: 600 },
23+
vertical: { size: 450 },
24+
}),
25+
},
2426
},
25-
},
27+
});
28+
const prefsPath = path.join(userDataDir, 'Default', 'Preferences');
29+
await fs.mkdir(path.dirname(prefsPath), { recursive: true });
30+
await fs.writeFile(prefsPath, prefs);
31+
}
32+
33+
const browserInstance = await puppeteer.launch({
34+
headless,
35+
devtools: !headless,
36+
ignoreDefaultArgs: [
37+
// Don't pop up "Chrome is being controlled by automated software"
38+
'--enable-automation',
39+
// Unsupported flag that pops up a warning
40+
'--enable-blink-features=IdleDetection',
41+
],
42+
args: [
43+
// Don't pop up "Chrome is not your default browser"
44+
'--no-default-browser-check',
45+
'--disable-features=ChromeLabs', // Remove little beaker icon next to URL bar
46+
],
47+
userDataDir,
2648
});
27-
const prefsPath = path.join(userDataDir, 'Default', 'Preferences');
28-
await fs.mkdir(path.dirname(prefsPath), { recursive: true });
29-
await fs.writeFile(prefsPath, prefs);
49+
const allPages = await browserInstance.pages();
50+
// Close startup page
51+
await Promise.all(allPages.map((p) => p.close()));
52+
const browserWSEndpoint = browserInstance.wsEndpoint();
53+
process.send!({ browserWSEndpoint });
54+
// eslint-disable-next-line no-process-exit
55+
browserInstance.on('disconnected', () => process.exit());
56+
} catch (error) {
57+
process.send!({ error: error.message });
3058
}
31-
32-
const browserInstance = await puppeteer.launch({
33-
headless,
34-
devtools: !headless,
35-
ignoreDefaultArgs: [
36-
// Don't pop up "Chrome is being controlled by automated software"
37-
'--enable-automation',
38-
// Unsupported flag that pops up a warning
39-
'--enable-blink-features=IdleDetection',
40-
],
41-
args: [
42-
// Don't pop up "Chrome is not your default browser"
43-
'--no-default-browser-check',
44-
'--disable-features=ChromeLabs', // Remove little beaker icon next to URL bar
45-
],
46-
userDataDir,
47-
});
48-
const allPages = await browserInstance.pages();
49-
// Close startup page
50-
await Promise.all(allPages.map((p) => p.close()));
51-
const browserWSEndpoint = browserInstance.wsEndpoint();
52-
process.send!({ browserWSEndpoint });
53-
// eslint-disable-next-line no-process-exit
54-
browserInstance.on('disconnected', () => process.exit());
5559
});

0 commit comments

Comments
 (0)