Skip to content

Commit f09f25e

Browse files
fix: Don't destroy boundary contents on error unless the boundary is an error boundary (#16746)
* fix: Don't destroy contents of boundaries on errors if they're not error boundaries * changeset * test * prettier * prettier * simplify test * oops --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 68d27f1 commit f09f25e

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

.changeset/tasty-trainers-sell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: don't destroy contents of `svelte:boundary` unless the boundary is an error boundary

packages/svelte/src/internal/client/dom/blocks/boundary.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ export class Boundary {
285285
var onerror = this.#props.onerror;
286286
let failed = this.#props.failed;
287287

288+
// If we have nothing to capture the error, or if we hit an error while
289+
// rendering the fallback, re-throw for another boundary to handle
290+
if (this.#is_creating_fallback || (!onerror && !failed)) {
291+
throw error;
292+
}
293+
288294
if (this.#main_effect) {
289295
destroy_effect(this.#main_effect);
290296
this.#main_effect = null;
@@ -346,12 +352,6 @@ export class Boundary {
346352
}
347353
};
348354

349-
// If we have nothing to capture the error, or if we hit an error while
350-
// rendering the fallback, re-throw for another boundary to handle
351-
if (this.#is_creating_fallback || (!onerror && !failed)) {
352-
throw error;
353-
}
354-
355355
var previous_reaction = active_reaction;
356356

357357
try {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { test } from '../../test';
2+
import { flushSync } from 'svelte';
3+
4+
export default test({
5+
test({ assert, target }) {
6+
const [button] = target.querySelectorAll('button');
7+
8+
assert.throws(() => {
9+
flushSync(() => button.click());
10+
}, /oops/);
11+
12+
assert.htmlEqual(
13+
target.innerHTML,
14+
`
15+
<button>throw</button>
16+
<p>some content</p>
17+
`
18+
);
19+
}
20+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script lang="ts">
2+
let should_throw = $state(false);
3+
4+
function throw_error() {
5+
throw new Error('oops');
6+
}
7+
</script>
8+
9+
<button onclick={() => should_throw = true}>
10+
throw
11+
</button>
12+
13+
<svelte:boundary>
14+
<p>some content</p>
15+
16+
{#if should_throw}
17+
{throw_error()}
18+
{/if}
19+
</svelte:boundary>

0 commit comments

Comments
 (0)