Skip to content

Commit ed7ebcd

Browse files
trueadmdummdidummRich-Harris
authored
feat: add error boundaries (#14211)
* feat: add error boundary support tweak tweak again retry -> reset tweaks add tests tweaks tweaks tweaks more tests more tests and tweaks comments tweak tweak tweak tweak tweak * tweak tweak tweak tweak more fixes tweak tweak more fixes changeset * Update packages/svelte/elements.d.ts Co-authored-by: Simon H <[email protected]> * Update .changeset/polite-peaches-do.md Co-authored-by: Simon H <[email protected]> * fix issue with rethrowing * handle fallback error * handle fallback error * add more test coverage * more tests * more bug fixes * guard against non-errors * add component_stack to error * alternative approach * remove spread support * lint * add to legacy ast * add to svelte-html * disallow anything but attributes on the boundary element * fix error * more validation * only create block when necessary * swap argument order - results in nicer-looking code in many cases * Update .changeset/polite-peaches-do.md * simplify a bit * simplify * move declaration closer to usage * push once * unused * tweaks * consistent naming * simplify * add a couple newlines * tweak comments * simplify * newlines * placeholder documentation * add some docs * Update packages/svelte/src/internal/client/dom/blocks/boundary.js Co-authored-by: Rich Harris <[email protected]> * Update packages/svelte/src/internal/client/dom/blocks/boundary.js Co-authored-by: Rich Harris <[email protected]> * Update packages/svelte/src/internal/client/dom/blocks/boundary.js Co-authored-by: Rich Harris <[email protected]> * fix type * fix link * explain what happens if onerror throws --------- Co-authored-by: Simon H <[email protected]> Co-authored-by: Simon Holthausen <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent f2eed15 commit ed7ebcd

File tree

78 files changed

+1199
-49
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1199
-49
lines changed

.changeset/polite-peaches-do.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': minor
3+
---
4+
5+
feat: add error boundaries with `<svelte:boundary>`
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
title: <svelte:boundary>
3+
---
4+
5+
```svelte
6+
<svelte:boundary onerror={handler}>...</svelte:boundary>
7+
```
8+
9+
Boundaries allow you to guard against errors in part of your app from breaking the app as a whole, and to recover from those errors.
10+
11+
If an error occurs while rendering or updating the children of a `<svelte:boundary>`, or running any [`$effect`]($effect) functions contained therein, the contents will be removed.
12+
13+
Errors occurring outside the rendering process (for example, in event handlers) are _not_ caught by error boundaries.
14+
15+
## Properties
16+
17+
For the boundary to do anything, one or both of `failed` and `onerror` must be provided.
18+
19+
### `failed`
20+
21+
If an `failed` snippet is provided, it will be rendered with the error that was thrown, and a `reset` function that recreates the contents ([demo](/playground/hello-world#H4sIAAAAAAAAE3VRy26DMBD8lS2tFCIh6JkAUlWp39Cq9EBg06CAbdlLArL87zWGKk8ORnhmd3ZnrD1WtOjFXqKO2BDGW96xqpBD5gXerm5QefG39mgQY9EIWHxueRMinLosti0UPsJLzggZKTeilLWgLGc51a3gkuCjKQ7DO7cXZotgJ3kLqzC6hmex1SZnSXTWYHcrj8LJjWTk0PHoZ8VqIdCOKayPykcpuQxAokJaG1dGybYj4gw4K5u6PKTasSbjXKgnIDlA8VvUdo-pzonraBY2bsH7HAl78mKSHZpgIcuHjq9jXSpZSLixRlveKYQUXhQVhL6GPobXAAb7BbNeyvNUs4qfRg3OnELLj5hqH9eQZqCnoBwR9lYcQxuVXeBzc8kMF8yXY4yNJ5oGiUzP_aaf_waTRGJib5_Ad3P_vbCuaYxzeNpbU0eUMPAOKh7Yw1YErgtoXyuYlPLzc10_xo_5A91zkQL_AgAA)):
22+
23+
```svelte
24+
<svelte:boundary>
25+
<FlakyComponent />
26+
27+
{#snippet failed(error, reset)}
28+
<button onclick={reset}>oops! try again</button>
29+
{/snippet}
30+
</svelte:boundary>
31+
```
32+
33+
> [!NOTE]
34+
> As with [snippets passed to components](snippet#Passing-snippets-to-components), the `failed` snippet can be passed explicitly as a property...
35+
>
36+
> ```svelte
37+
> <svelte:boundary {failed}>...</svelte:boundary>
38+
> ```
39+
>
40+
> ...or implicitly by declaring it directly inside the boundary, as in the example above.
41+
42+
### `onerror`
43+
44+
If an `onerror` function is provided, it will be called with the same two `error` and `reset` arguments. This is useful for tracking the error with an error reporting service...
45+
46+
```svelte
47+
<svelte:boundary onerror={(e) => report(e)}>
48+
...
49+
</svelte:boundary>
50+
```
51+
52+
...or using `error` and `reset` outside the boundary itself:
53+
54+
```svelte
55+
<script>
56+
let error = $state(null);
57+
let reset = $state(() => {});
58+
59+
function onerror(e, r) {
60+
error = e;
61+
reset = r;
62+
}
63+
</script>
64+
65+
<svelte:boundary {onerror}>
66+
<FlakyComponent />
67+
</svelte:boundary>
68+
69+
{#if error}
70+
<button onclick={() => {
71+
error = null;
72+
reset();
73+
}}>
74+
oops! try again
75+
</button>
76+
{/if}
77+
```
78+
79+
If an error occurs inside the `onerror` function (or if you rethrow the error), it will be handled by a parent boundary if such exists.

documentation/docs/98-reference/.generated/compile-errors.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,18 @@ A component can have a single top-level `<style>` element
762762
`<svelte:body>` does not support non-event attributes or spread attributes
763763
```
764764

765+
### svelte_boundary_invalid_attribute
766+
767+
```
768+
Valid attributes on `<svelte:boundary>` are `onerror` and `failed`
769+
```
770+
771+
### svelte_boundary_invalid_attribute_value
772+
773+
```
774+
Attribute value must be a non-string expression
775+
```
776+
765777
### svelte_component_invalid_this
766778

767779
```

packages/svelte/elements.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,10 @@ export interface SvelteHTMLElements {
20442044
[name: string]: any;
20452045
};
20462046
'svelte:head': { [name: string]: any };
2047+
'svelte:boundary': {
2048+
onerror?: (error: unknown, reset: () => void) => void;
2049+
failed?: import('svelte').Snippet<[error: unknown, reset: () => void]>;
2050+
};
20472051

20482052
[name: string]: { [name: string]: any };
20492053
}

0 commit comments

Comments
 (0)