Skip to content

Commit c468c6d

Browse files
committed
alternative approach
1 parent 5be2334 commit c468c6d

File tree

4 files changed

+41
-22
lines changed

4 files changed

+41
-22
lines changed

packages/svelte/elements.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,8 +2027,8 @@ export interface SvelteHTMLElements {
20272027
};
20282028
'svelte:head': { [name: string]: any };
20292029
'svelte:boundary': {
2030-
onerror?: (error: Error, reset: () => void) => void;
2031-
failed?: import('svelte').Snippet<[error: Error, reset: () => void]>;
2030+
onerror?: (error: unknown, reset: () => void) => void;
2031+
failed?: import('svelte').Snippet<[error: unknown, reset: () => void]>;
20322032
};
20332033

20342034
[name: string]: { [name: string]: any };

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import {
77
active_reaction,
88
component_context,
99
handle_error,
10+
is_throwing_error,
1011
set_active_effect,
1112
set_active_reaction,
12-
set_component_context
13+
set_component_context,
14+
reset_is_throwing_error
1315
} from '../../runtime.js';
1416
import {
1517
hydrate_next,
@@ -45,8 +47,8 @@ function with_boundary(boundary, fn) {
4547
* @param {TemplateNode} node
4648
* @param {((anchor: Node) => void)} boundary_fn
4749
* @param {{
48-
* onerror?: (error: Error, reset: () => void) => void,
49-
* failed?: (anchor: Node, error: () => Error, reset: () => () => void) => void
50+
* onerror?: (error: unknown, reset: () => void) => void,
51+
* failed?: (anchor: Node, error: () => unknown, reset: () => () => void) => void
5052
* }} props
5153
* @returns {void}
5254
*/
@@ -62,7 +64,7 @@ export function boundary(node, boundary_fn, props) {
6264
var is_creating_fallback = false;
6365

6466
// We re-use the effect's fn property to avoid allocation of an additional field
65-
boundary.fn = (/** @type { Error }} */ error) => {
67+
boundary.fn = (/** @type { unknown }} */ error) => {
6668
var onerror = props.onerror;
6769
let failed_snippet = props.failed;
6870

@@ -82,6 +84,7 @@ export function boundary(node, boundary_fn, props) {
8284
boundary_effect = null;
8385
is_creating_fallback = false;
8486
boundary_effect = branch(() => boundary_fn(anchor));
87+
reset_is_throwing_error();
8588
});
8689
};
8790

@@ -114,8 +117,9 @@ export function boundary(node, boundary_fn, props) {
114117
);
115118
});
116119
} catch (error) {
117-
handle_error(error, boundary, boundary.ctx);
120+
handle_error(error, boundary, null, boundary.ctx);
118121
}
122+
reset_is_throwing_error();
119123
is_creating_fallback = false;
120124
});
121125
});
@@ -127,6 +131,7 @@ export function boundary(node, boundary_fn, props) {
127131
}
128132

129133
boundary_effect = branch(() => boundary_fn(anchor));
134+
reset_is_throwing_error();
130135
}, EFFECT_TRANSPARENT | BOUNDARY_EFFECT);
131136

132137
if (hydrating) {

packages/svelte/src/internal/client/runtime.js

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@ import { legacy_mode_flag } from '../flags/index.js';
3838

3939
const FLUSH_MICROTASK = 0;
4040
const FLUSH_SYNC = 1;
41-
4241
// Used for DEV time error handling
4342
/** @param {WeakSet<Error>} value */
4443
const handled_errors = new WeakSet();
44+
export let is_throwing_error = false;
45+
4546
// Used for controlling the flush of effects.
4647
let scheduler_mode = FLUSH_MICROTASK;
4748
// Used for handling scheduling
@@ -230,7 +231,7 @@ export function check_dirtiness(reaction) {
230231
}
231232

232233
/**
233-
* @param {Error} error
234+
* @param {unknown} error
234235
* @param {Effect} effect
235236
*/
236237
function propagate_error(error, effect) {
@@ -254,7 +255,7 @@ function propagate_error(error, effect) {
254255
}
255256
current = parent;
256257
}
257-
258+
is_throwing_error = false;
258259
throw error;
259260
}
260261

@@ -268,30 +269,43 @@ function should_rethrow_error(effect) {
268269
);
269270
}
270271

272+
export function reset_is_throwing_error() {
273+
is_throwing_error = false;
274+
}
275+
271276
/**
272277
* @param {unknown} error
273278
* @param {Effect} effect
279+
* @param {Effect | null} previous_effect
274280
* @param {ComponentContext | null} component_context
275281
*/
276-
export function handle_error(error, effect, component_context) {
277-
if (!(error instanceof Error)) {
278-
throw error;
279-
}
280-
281-
if (handled_errors.has(error)) {
282+
export function handle_error(error, effect, previous_effect, component_context) {
283+
if (is_throwing_error) {
284+
if (previous_effect === null) {
285+
is_throwing_error = false;
286+
}
282287
if (should_rethrow_error(effect)) {
283288
throw error;
284289
}
285290
return;
286291
}
287292

288-
handled_errors.add(error);
293+
if (previous_effect !== null) {
294+
is_throwing_error = true;
295+
}
289296

290-
if (!DEV || component_context === null) {
297+
if (
298+
!DEV ||
299+
component_context === null ||
300+
!(error instanceof Error) ||
301+
handled_errors.has(error)
302+
) {
291303
propagate_error(error, effect);
292304
return;
293305
}
294306

307+
handled_errors.add(error);
308+
295309
const component_stack = [];
296310

297311
const effect_name = effect.fn?.name;
@@ -507,7 +521,7 @@ export function update_effect(effect) {
507521
dev_effect_stack.push(effect);
508522
}
509523
} catch (error) {
510-
handle_error(error, effect, previous_component_context || effect.ctx);
524+
handle_error(error, effect, previous_effect, previous_component_context || effect.ctx);
511525
} finally {
512526
active_effect = previous_effect;
513527

@@ -608,7 +622,7 @@ function flush_queued_effects(effects) {
608622
}
609623
}
610624
} catch (error) {
611-
handle_error(error, effect, effect.ctx);
625+
handle_error(error, effect, null, effect.ctx);
612626
}
613627
}
614628
}
@@ -688,7 +702,7 @@ function process_effects(effect, collected_effects) {
688702
update_effect(current_effect);
689703
}
690704
} catch (error) {
691-
handle_error(error, current_effect, current_effect.ctx);
705+
handle_error(error, current_effect, null, current_effect.ctx);
692706
}
693707
}
694708

packages/svelte/tests/runtime-runes/samples/error-boundary-17/Child.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
$effect.pre(() => {
77
if (count > 1) {
8-
throw new Error('too high');
8+
throw 'too high';
99
}
1010
});
1111
</script>

0 commit comments

Comments
 (0)