You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: robustify reset calls in error boundaries (#16171)
Fixes#16134
* Add a warning when the misuse of `reset` in an `error:boundary` causes an error to be thrown when flushing the boundary content
* Prevent uncaught errors to make test fails when they are expected and are fired during template effects flush
* reset should just be a noop after the first call
* correctly handle errors inside boundary during reset
* handle errors in the correct boundary
---------
Co-authored-by: Rich Harris <[email protected]>
Copy file name to clipboardExpand all lines: documentation/docs/98-reference/.generated/client-errors.md
+20Lines changed: 20 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -238,3 +238,23 @@ let odd = $derived(!even);
238
238
```
239
239
240
240
If side-effects are unavoidable, use [`$effect`]($effect) instead.
241
+
242
+
### svelte_boundary_reset_onerror
243
+
244
+
```
245
+
A `<svelte:boundary>` `reset` function cannot be called while an error is still being handled
246
+
```
247
+
248
+
If a [`<svelte:boundary>`](https://svelte.dev/docs/svelte/svelte-boundary) has an `onerror` function, it must not call the provided `reset` function synchronously since the boundary is still in a broken state. Typically, `reset()` is called later, once the error has been resolved.
249
+
250
+
If it's possible to resolve the error inside the `onerror` callback, you must at least wait for the boundary to settle before calling `reset()`, for example using [`tick`](https://svelte.dev/docs/svelte/lifecycle-hooks#tick):
Copy file name to clipboardExpand all lines: documentation/docs/98-reference/.generated/client-warnings.md
+26Lines changed: 26 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -312,6 +312,32 @@ Reactive `$state(...)` proxies and the values they proxy have different identiti
312
312
313
313
To resolve this, ensure you're comparing values where both values were created with `$state(...)`, or neither were. Note that `$state.raw(...)` will _not_ create a state proxy.
314
314
315
+
### svelte_boundary_reset_noop
316
+
317
+
```
318
+
A`<svelte:boundary>``reset`function only resets the boundary the first time it is called
319
+
```
320
+
321
+
When an error occurs while rendering the contents of a [`<svelte:boundary>`](https://svelte.dev/docs/svelte/svelte-boundary), the `onerror` handler is called with the error plus a `reset` function that attempts to re-render the contents.
322
+
323
+
This`reset`function should only be called once. After that, it has no effect — in a case like this, where a reference to `reset` is stored outside the boundary, clicking the button while `<Contents />` is rendered will _not_ cause the contents to be rendered again.
Copy file name to clipboardExpand all lines: packages/svelte/messages/client-errors/errors.md
+18Lines changed: 18 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -184,3 +184,21 @@ let odd = $derived(!even);
184
184
```
185
185
186
186
If side-effects are unavoidable, use [`$effect`]($effect) instead.
187
+
188
+
## svelte_boundary_reset_onerror
189
+
190
+
> A `<svelte:boundary>``reset` function cannot be called while an error is still being handled
191
+
192
+
If a [`<svelte:boundary>`](https://svelte.dev/docs/svelte/svelte-boundary) has an `onerror` function, it must not call the provided `reset` function synchronously since the boundary is still in a broken state. Typically, `reset()` is called later, once the error has been resolved.
193
+
194
+
If it's possible to resolve the error inside the `onerror` callback, you must at least wait for the boundary to settle before calling `reset()`, for example using [`tick`](https://svelte.dev/docs/svelte/lifecycle-hooks#tick):
Copy file name to clipboardExpand all lines: packages/svelte/messages/client-warnings/warnings.md
+24Lines changed: 24 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -272,6 +272,30 @@ To silence the warning, ensure that `value`:
272
272
273
273
To resolve this, ensure you're comparing values where both values were created with `$state(...)`, or neither were. Note that `$state.raw(...)` will _not_ create a state proxy.
274
274
275
+
## svelte_boundary_reset_noop
276
+
277
+
> A `<svelte:boundary>``reset` function only resets the boundary the first time it is called
278
+
279
+
When an error occurs while rendering the contents of a [`<svelte:boundary>`](https://svelte.dev/docs/svelte/svelte-boundary), the `onerror` handler is called with the error plus a `reset` function that attempts to re-render the contents.
280
+
281
+
This `reset` function should only be called once. After that, it has no effect — in a case like this, where a reference to `reset` is stored outside the boundary, clicking the button while `<Contents />` is rendered will _not_ cause the contents to be rendered again.
282
+
283
+
```svelte
284
+
<script>
285
+
let reset;
286
+
</script>
287
+
288
+
<button onclick={reset}>reset</button>
289
+
290
+
<svelte:boundary onerror={(e, r) => (reset = r)}>
291
+
<!-- contents -->
292
+
293
+
{#snippet failed(e)}
294
+
<p>oops! {e.message}</p>
295
+
{/snippet}
296
+
</svelte:boundary>
297
+
```
298
+
275
299
## transition_slide_display
276
300
277
301
> The `slide` transition does not work correctly for elements with `display:%value%`
* A `<svelte:boundary>` `reset` function cannot be called while an error is still being handled
430
+
* @returns {never}
431
+
*/
432
+
exportfunctionsvelte_boundary_reset_onerror(){
433
+
if(DEV){
434
+
consterror=newError(`svelte_boundary_reset_onerror\nA \`<svelte:boundary>\` \`reset\` function cannot be called while an error is still being handled\nhttps://svelte.dev/e/svelte_boundary_reset_onerror`);
Copy file name to clipboardExpand all lines: packages/svelte/src/internal/client/warnings.js
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -224,6 +224,17 @@ export function state_proxy_equality_mismatch(operator) {
224
224
}
225
225
}
226
226
227
+
/**
228
+
* A `<svelte:boundary>` `reset` function only resets the boundary the first time it is called
229
+
*/
230
+
exportfunctionsvelte_boundary_reset_noop(){
231
+
if(DEV){
232
+
console.warn(`%c[svelte] svelte_boundary_reset_noop\n%cA \`<svelte:boundary>\` \`reset\` function only resets the boundary the first time it is called\nhttps://svelte.dev/e/svelte_boundary_reset_noop`,bold,normal);
0 commit comments