Skip to content

Commit 8e9eb10

Browse files
authored
show errors (sveltejs#91)
* display errors (sveltejs#59) * tweak error messages * goddamn * oops * tweaks
1 parent ab39d73 commit 8e9eb10

File tree

5 files changed

+111
-58
lines changed

5 files changed

+111
-58
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"type": "module",
2929
"dependencies": {
3030
"@fontsource/roboto-mono": "^4.5.7",
31-
"@webcontainer/api": "^0.0.1",
31+
"@webcontainer/api": "^0.0.4",
3232
"adm-zip": "^0.5.9",
3333
"base64-js": "^1.5.1",
3434
"marked": "^4.0.16",

pnpm-lock.yaml

Lines changed: 22 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/client/adapters/webcontainer/index.js

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import { load } from '@webcontainer/api';
22
import base64 from 'base64-js';
33
import { ready } from '../common/index.js';
44

5-
const WebContainer = await load();
6-
75
/**
86
* @param {import('$lib/types').Stub[]} stubs
97
* @returns {Promise<import('$lib/types').Adapter>}
@@ -19,31 +17,49 @@ export async function create(stubs) {
1917
file: { contents: common.unzip }
2018
};
2119

22-
const vm = await WebContainer.boot();
23-
await vm.loadFiles(tree);
20+
if (/safari/i.test(navigator.userAgent) && !/chrome/i.test(navigator.userAgent)) {
21+
throw new Error('WebContainers are not supported by Safari');
22+
}
2423

25-
const unzip = await vm.run(
26-
{
27-
command: 'node',
28-
args: ['unzip.cjs']
29-
},
30-
{
31-
stderr: (data) => console.error(`[unzip] ${data}`)
32-
}
33-
);
24+
/** @type {import('@webcontainer/api').WebContainer} */
25+
let vm;
26+
27+
const base = await new Promise(async (fulfil, reject) => {
28+
setTimeout(() => {
29+
reject(new Error('Timed out'));
30+
}, 15000);
3431

35-
const code = await unzip.onExit;
32+
const WebContainer = await load();
3633

37-
if (code !== 0) {
38-
throw new Error('Failed to initialize WebContainer');
39-
}
34+
vm = await WebContainer.boot();
35+
36+
vm.on('error', (error) => {
37+
reject(new Error(error.message));
38+
});
4039

41-
const base = await new Promise(async (fulfil, reject) => {
4240
vm.on('server-ready', (port, base) => {
4341
console.log(`server ready on port ${port} at ${performance.now()}: ${base}`);
4442
fulfil(base);
4543
});
4644

45+
await vm.loadFiles(tree);
46+
47+
const unzip = await vm.run(
48+
{
49+
command: 'node',
50+
args: ['unzip.cjs']
51+
},
52+
{
53+
stderr: (data) => console.error(`[unzip] ${data}`)
54+
}
55+
);
56+
57+
const code = await unzip.onExit;
58+
59+
if (code !== 0) {
60+
reject(new Error('Failed to initialize WebContainer'));
61+
}
62+
4763
await vm.run(
4864
{ command: 'turbo', args: ['run', 'dev'] },
4965
{

src/routes/tutorial/[slug]/_/Loading.svelte

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,43 @@
11
<script>
22
/** @type {boolean} */
33
export let initial;
4+
5+
/** @type {Error | null} */
6+
export let error;
7+
8+
/** @param {Error} error */
9+
function get_error_message(error) {
10+
if (/safari/i.test(navigator.userAgent) && !/chrome/i.test(navigator.userAgent)) {
11+
return '<p>This app requires modern web platform features. Please use a browser other than Safari.</p>';
12+
}
13+
14+
if (/firefox/i.test(navigator.userAgent)) {
15+
return `<p>Failed to start WebContainer. You may need to enable third party cookies and disable Enhanced Tracking Protection.</p><small>Error message: ${error.message}</small>`;
16+
}
17+
18+
return `<p>Failed to start WebContainer. You may need to enable third party cookies.</p><small>Error message: ${error.message}</small>`;
19+
}
420
</script>
521

6-
<div class="loading">
7-
{#if initial}
8-
<p>initializing... this may take a few seconds</p>
9-
{/if}
22+
<div class="loading" class:error>
23+
{#if error}
24+
{@html get_error_message(error)}
25+
{:else}
26+
{#if initial}
27+
<p>initializing... this may take a few seconds</p>
28+
{/if}
1029

11-
<svg width="107" height="128" viewBox="0 0 107 128">
12-
<path
13-
d="M94.1566,22.8189c-10.4-14.8851-30.94-19.2971-45.7914-9.8348L22.2825,29.6078A29.9234,29.9234,0,0,0,8.7639,49.6506a31.5136,31.5136,0,0,0,3.1076,20.2318A30.0061,30.0061,0,0,0,7.3953,81.0653a31.8886,31.8886,0,0,0,5.4473,24.1157c10.4022,14.8865,30.9423,19.2966,45.7914,9.8348L84.7167,98.3921A29.9177,29.9177,0,0,0,98.2353,78.3493,31.5263,31.5263,0,0,0,95.13,58.117a30,30,0,0,0,4.4743-11.1824,31.88,31.88,0,0,0-5.4473-24.1157"
14-
style="fill: #ff3e00"
15-
/>
16-
<path
17-
d="M45.8171,106.5815A20.7182,20.7182,0,0,1,23.58,98.3389a19.1739,19.1739,0,0,1-3.2766-14.5025,18.1886,18.1886,0,0,1,.6233-2.4357l.4912-1.4978,1.3363.9815a33.6443,33.6443,0,0,0,10.203,5.0978l.9694.2941-.0893.9675a5.8474,5.8474,0,0,0,1.052,3.8781,6.2389,6.2389,0,0,0,6.6952,2.485,5.7449,5.7449,0,0,0,1.6021-.7041L69.27,76.281a5.4306,5.4306,0,0,0,2.4506-3.631,5.7948,5.7948,0,0,0-.9875-4.3712,6.2436,6.2436,0,0,0-6.6978-2.4864,5.7427,5.7427,0,0,0-1.6.7036l-9.9532,6.3449a19.0329,19.0329,0,0,1-5.2965,2.3259,20.7181,20.7181,0,0,1-22.2368-8.2427,19.1725,19.1725,0,0,1-3.2766-14.5024,17.9885,17.9885,0,0,1,8.13-12.0513L55.8833,23.7472a19.0038,19.0038,0,0,1,5.3-2.3287A20.7182,20.7182,0,0,1,83.42,29.6611a19.1739,19.1739,0,0,1,3.2766,14.5025,18.4,18.4,0,0,1-.6233,2.4357l-.4912,1.4978-1.3356-.98a33.6175,33.6175,0,0,0-10.2037-5.1l-.9694-.2942.0893-.9675a5.8588,5.8588,0,0,0-1.052-3.878,6.2389,6.2389,0,0,0-6.6952-2.485,5.7449,5.7449,0,0,0-1.6021.7041L37.73,51.719a5.4218,5.4218,0,0,0-2.4487,3.63,5.7862,5.7862,0,0,0,.9856,4.3717,6.2437,6.2437,0,0,0,6.6978,2.4864,5.7652,5.7652,0,0,0,1.602-.7041l9.9519-6.3425a18.978,18.978,0,0,1,5.2959-2.3278,20.7181,20.7181,0,0,1,22.2368,8.2427,19.1725,19.1725,0,0,1,3.2766,14.5024,17.9977,17.9977,0,0,1-8.13,12.0532L51.1167,104.2528a19.0038,19.0038,0,0,1-5.3,2.3287"
18-
style="fill: #fff"
19-
/>
20-
</svg>
30+
<svg width="107" height="128" viewBox="0 0 107 128">
31+
<path
32+
d="M94.1566,22.8189c-10.4-14.8851-30.94-19.2971-45.7914-9.8348L22.2825,29.6078A29.9234,29.9234,0,0,0,8.7639,49.6506a31.5136,31.5136,0,0,0,3.1076,20.2318A30.0061,30.0061,0,0,0,7.3953,81.0653a31.8886,31.8886,0,0,0,5.4473,24.1157c10.4022,14.8865,30.9423,19.2966,45.7914,9.8348L84.7167,98.3921A29.9177,29.9177,0,0,0,98.2353,78.3493,31.5263,31.5263,0,0,0,95.13,58.117a30,30,0,0,0,4.4743-11.1824,31.88,31.88,0,0,0-5.4473-24.1157"
33+
style="fill: #ff3e00"
34+
/>
35+
<path
36+
d="M45.8171,106.5815A20.7182,20.7182,0,0,1,23.58,98.3389a19.1739,19.1739,0,0,1-3.2766-14.5025,18.1886,18.1886,0,0,1,.6233-2.4357l.4912-1.4978,1.3363.9815a33.6443,33.6443,0,0,0,10.203,5.0978l.9694.2941-.0893.9675a5.8474,5.8474,0,0,0,1.052,3.8781,6.2389,6.2389,0,0,0,6.6952,2.485,5.7449,5.7449,0,0,0,1.6021-.7041L69.27,76.281a5.4306,5.4306,0,0,0,2.4506-3.631,5.7948,5.7948,0,0,0-.9875-4.3712,6.2436,6.2436,0,0,0-6.6978-2.4864,5.7427,5.7427,0,0,0-1.6.7036l-9.9532,6.3449a19.0329,19.0329,0,0,1-5.2965,2.3259,20.7181,20.7181,0,0,1-22.2368-8.2427,19.1725,19.1725,0,0,1-3.2766-14.5024,17.9885,17.9885,0,0,1,8.13-12.0513L55.8833,23.7472a19.0038,19.0038,0,0,1,5.3-2.3287A20.7182,20.7182,0,0,1,83.42,29.6611a19.1739,19.1739,0,0,1,3.2766,14.5025,18.4,18.4,0,0,1-.6233,2.4357l-.4912,1.4978-1.3356-.98a33.6175,33.6175,0,0,0-10.2037-5.1l-.9694-.2942.0893-.9675a5.8588,5.8588,0,0,0-1.052-3.878,6.2389,6.2389,0,0,0-6.6952-2.485,5.7449,5.7449,0,0,0-1.6021.7041L37.73,51.719a5.4218,5.4218,0,0,0-2.4487,3.63,5.7862,5.7862,0,0,0,.9856,4.3717,6.2437,6.2437,0,0,0,6.6978,2.4864,5.7652,5.7652,0,0,0,1.602-.7041l9.9519-6.3425a18.978,18.978,0,0,1,5.2959-2.3278,20.7181,20.7181,0,0,1,22.2368,8.2427,19.1725,19.1725,0,0,1,3.2766,14.5024,17.9977,17.9977,0,0,1-8.13,12.0532L51.1167,104.2528a19.0038,19.0038,0,0,1-5.3,2.3287"
37+
style="fill: #fff"
38+
/>
39+
</svg>
40+
{/if}
2141
</div>
2242

2343
<style>
@@ -40,6 +60,15 @@
4060
color: #999;
4161
}
4262
63+
.error {
64+
align-items: start;
65+
justify-content: start;
66+
}
67+
68+
.error :global(p) {
69+
color: #f00;
70+
}
71+
4372
svg {
4473
width: 100px;
4574
height: 100px;

src/routes/tutorial/[slug]/index.svelte

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
let loading = true;
5050
let initial = true;
5151
52+
/** @type {Error | null} */
53+
let error = null;
54+
5255
/** @type {Record<string, boolean>}*/
5356
let complete_states = {};
5457
let completed = false;
@@ -142,7 +145,12 @@
142145
? await import('$lib/client/adapters/filesystem/index.js')
143146
: await import('$lib/client/adapters/webcontainer/index.js');
144147
145-
adapter = await module.create(Object.values(b));
148+
try {
149+
adapter = await module.create(Object.values(b));
150+
} catch (e) {
151+
error = /** @type {Error} */ (e);
152+
return;
153+
}
146154
}
147155
148156
set_iframe_src(adapter.base);
@@ -404,8 +412,8 @@
404412
<div class="content">
405413
<iframe bind:this={iframe} title="Output" />
406414
407-
{#if loading}
408-
<Loading {initial} />
415+
{#if loading || error}
416+
<Loading {initial} {error} />
409417
{/if}
410418
</div>
411419
</section>

0 commit comments

Comments
 (0)