mirror of https://github.com/sveltejs/svelte
fix: run boundary `onerror` callbacks in a microtask, in case they result in the boundary's destruction (#17561)
* fix: mark parent effect as dirty on error boundary initialization This change ensures that if an error occurs while a parent effect is still initializing, the parent effect is marked as dirty and scheduled to re-run. This addresses scenarios where state updates in the onerror handler do not trigger a re-evaluation of the condition, improving error handling in Svelte components. * chore: add changeset for #17553 * fix: run boundary callbacks in a microtask, in case they result in the boundary's destruction --------- Co-authored-by: frozenflux2 <snowflake30518@gmail.com>pull/17560/head
parent
8c8a22add4
commit
30cea1f9a0
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: run boundary `onerror` callbacks in a microtask, in case they result in the boundary's destruction
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
throw new Error('child error');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>Child content</p>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['client'],
|
||||||
|
test({ assert, target }) {
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
// When exception is set by onerror, the {#if !exception} block should hide
|
||||||
|
// and only the {#if exception} block should be visible
|
||||||
|
assert.htmlEqual(target.innerHTML, '<p>caught error: child error</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<script>
|
||||||
|
import Child from './Child.svelte';
|
||||||
|
|
||||||
|
let exception = $state();
|
||||||
|
const onerror = (e) => {
|
||||||
|
exception = e;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !exception}
|
||||||
|
<p>condition is {String(!exception)}</p>
|
||||||
|
<svelte:boundary {onerror}>
|
||||||
|
<Child />
|
||||||
|
</svelte:boundary>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if exception}
|
||||||
|
<p>caught error: {exception.message}</p>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<script>
|
||||||
|
// it's important for the test that this isn't an `Error`
|
||||||
|
throw 'child error'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
boom
|
||||||
|
</p>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['client'],
|
||||||
|
test({ assert, target }) {
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
// When exception is set by onerror, the {#if !exception} block should hide
|
||||||
|
// and only the {#if exception} block should be visible
|
||||||
|
assert.htmlEqual(target.innerHTML, '<p>caught error: child error</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<script>
|
||||||
|
import Child from './Child.svelte';
|
||||||
|
|
||||||
|
let exception = $state();
|
||||||
|
const onerror = (e) => {
|
||||||
|
exception = e;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !exception}
|
||||||
|
<p>condition is {String(!exception)}</p>
|
||||||
|
<svelte:boundary {onerror}>
|
||||||
|
<Child />
|
||||||
|
</svelte:boundary>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if exception}
|
||||||
|
<p>caught error: {exception}</p>
|
||||||
|
{/if}
|
||||||
Loading…
Reference in new issue