Skip to content

Commit

Permalink
tweak
Browse files Browse the repository at this point in the history
tweak

tweak

tweak

more fixes

tweak

tweak

more fixes

changeset
  • Loading branch information
trueadm committed Nov 7, 2024
1 parent 2acde4c commit d2e035b
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/polite-peaches-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

feat: adds error boundaries
10 changes: 1 addition & 9 deletions packages/svelte/src/internal/client/dom/blocks/boundary.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,9 @@ export function boundary(node, boundary_fn, props) {

block(() => {
var boundary = /** @type {Effect} */ (active_effect);
var start = hydrate_node;

// We re-use the effect's fn property to avoid allocation of an additional field
boundary.fn = (/** @type {{ error?: Error }} */ payload) => {
let { error } = payload;

// In the future, boundaries might handle other things other than errors
if (!error) {
return;
}

boundary.fn = (/** @type { Error }} */ error) => {
var onerror = props.onerror;
let failed_snippet = props.failed;

Expand Down
52 changes: 33 additions & 19 deletions packages/svelte/src/internal/client/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,10 @@ function propagate_error(error, effect) {
if ((current.f & BOUNDARY_EFFECT) !== 0) {
try {
// @ts-ignore
current.fn({ error });
current.fn(error);
} catch {
// Remove boundary flag from effect
current.f ^= BOUNDARY_EFFECT;
current = parent;
continue;
}
Expand Down Expand Up @@ -485,7 +487,7 @@ export function update_effect(effect) {
dev_effect_stack.push(effect);
}
} catch (error) {
handle_error(/** @type {Error} */ (error), effect, previous_component_context);
handle_error(/** @type {Error} */ (error), effect, previous_component_context || effect.ctx);
} finally {
active_effect = previous_effect;

Expand Down Expand Up @@ -565,22 +567,28 @@ function flush_queued_effects(effects) {
for (var i = 0; i < length; i++) {
var effect = effects[i];

if ((effect.f & (DESTROYED | INERT)) === 0 && check_dirtiness(effect)) {
update_effect(effect);

// Effects with no dependencies or teardown do not get added to the effect tree.
// Deferred effects (e.g. `$effect(...)`) _are_ added to the tree because we
// don't know if we need to keep them until they are executed. Doing the check
// here (rather than in `update_effect`) allows us to skip the work for
// immediate effects.
if (effect.deps === null && effect.first === null && effect.nodes_start === null) {
if (effect.teardown === null) {
// remove this effect from the graph
unlink_effect(effect);
} else {
// keep the effect in the graph, but free up some memory
effect.fn = null;
if ((effect.f & (DESTROYED | INERT)) === 0) {
try {
if (check_dirtiness(effect)) {
update_effect(effect);

// Effects with no dependencies or teardown do not get added to the effect tree.
// Deferred effects (e.g. `$effect(...)`) _are_ added to the tree because we
// don't know if we need to keep them until they are executed. Doing the check
// here (rather than in `update_effect`) allows us to skip the work for
// immediate effects.
if (effect.deps === null && effect.first === null && effect.nodes_start === null) {
if (effect.teardown === null) {
// remove this effect from the graph
unlink_effect(effect);
} else {
// keep the effect in the graph, but free up some memory
effect.fn = null;
}
}
}
} catch (error) {
handle_error(/** @type {Error} */ (error), effect, effect.ctx);
}
}
}
Expand Down Expand Up @@ -653,8 +661,14 @@ function process_effects(effect, collected_effects) {
if ((flags & RENDER_EFFECT) !== 0) {
if (is_branch) {
current_effect.f ^= CLEAN;
} else if (check_dirtiness(current_effect)) {
update_effect(current_effect);
} else {
try {
if (check_dirtiness(current_effect)) {
update_effect(current_effect);
}
} catch (error) {
handle_error(/** @type {Error} */ (error), current_effect, current_effect.ctx);
}
}

var child = current_effect.first;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { test } from '../../test';

export default test({
test({ assert, target, logs }) {
const btn = target.querySelector('button');

btn?.click();
flushSync();

assert.htmlEqual(target.innerHTML, `<button>change</button><p>Error occured</p>`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script>
let count = $state(0);
const things = $derived.by(() => {
if (count === 1) {
throw new Error('123')
}
return [1, 2 ,3]
})
</script>

<button onclick={() => count++}>change</button>

<svelte:boundary>
{#each things as thing}
<p>{thing}</p>
{/each}

{#snippet failed()}
<p>Error occured</p>
{/snippet}
</svelte:boundary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
const { things } = $props();
$effect(() => {
things
})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { test } from '../../test';

export default test({
test({ assert, target, logs }) {
const btn = target.querySelector('button');

btn?.click();
flushSync();

assert.htmlEqual(target.innerHTML, `<button>change</button><p>Error occured</p>`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script>
import Child from './Child.svelte';
let count = $state(0);
const things = $derived.by(() => {
if (count === 1) {
throw new Error('123')
}
return [1, 2 ,3]
})
</script>

<button onclick={() => count++}>change</button>

<svelte:boundary>
<Child {things} />

{#snippet failed()}
<p>Error occured</p>
{/snippet}
</svelte:boundary>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</svelte:boundary>

{#snippet failed(e, retry)}
<div>{e.message}</div>
<div>too high</div>
<button onclick={retry}>Retry</button>
{/snippet}
</svelte:boundary>
Expand Down

0 comments on commit d2e035b

Please sign in to comment.