alternative approach

pull/14211/head
Dominic Gannaway 2 years ago
parent 5be2334ed8
commit c468c6d686

@ -2027,8 +2027,8 @@ export interface SvelteHTMLElements {
};
'svelte:head': { [name: string]: any };
'svelte:boundary': {
onerror?: (error: Error, reset: () => void) => void;
failed?: import('svelte').Snippet<[error: Error, reset: () => void]>;
onerror?: (error: unknown, reset: () => void) => void;
failed?: import('svelte').Snippet<[error: unknown, reset: () => void]>;
};
[name: string]: { [name: string]: any };

@ -7,9 +7,11 @@ import {
active_reaction,
component_context,
handle_error,
is_throwing_error,
set_active_effect,
set_active_reaction,
set_component_context
set_component_context,
reset_is_throwing_error
} from '../../runtime.js';
import {
hydrate_next,
@ -45,8 +47,8 @@ function with_boundary(boundary, fn) {
* @param {TemplateNode} node
* @param {((anchor: Node) => void)} boundary_fn
* @param {{
* onerror?: (error: Error, reset: () => void) => void,
* failed?: (anchor: Node, error: () => Error, reset: () => () => void) => void
* onerror?: (error: unknown, reset: () => void) => void,
* failed?: (anchor: Node, error: () => unknown, reset: () => () => void) => void
* }} props
* @returns {void}
*/
@ -62,7 +64,7 @@ export function boundary(node, boundary_fn, props) {
var is_creating_fallback = false;
// We re-use the effect's fn property to avoid allocation of an additional field
boundary.fn = (/** @type { Error }} */ error) => {
boundary.fn = (/** @type { unknown }} */ error) => {
var onerror = props.onerror;
let failed_snippet = props.failed;
@ -82,6 +84,7 @@ export function boundary(node, boundary_fn, props) {
boundary_effect = null;
is_creating_fallback = false;
boundary_effect = branch(() => boundary_fn(anchor));
reset_is_throwing_error();
});
};
@ -114,8 +117,9 @@ export function boundary(node, boundary_fn, props) {
);
});
} catch (error) {
handle_error(error, boundary, boundary.ctx);
handle_error(error, boundary, null, boundary.ctx);
}
reset_is_throwing_error();
is_creating_fallback = false;
});
});
@ -127,6 +131,7 @@ export function boundary(node, boundary_fn, props) {
}
boundary_effect = branch(() => boundary_fn(anchor));
reset_is_throwing_error();
}, EFFECT_TRANSPARENT | BOUNDARY_EFFECT);
if (hydrating) {

@ -38,10 +38,11 @@ import { legacy_mode_flag } from '../flags/index.js';
const FLUSH_MICROTASK = 0;
const FLUSH_SYNC = 1;
// Used for DEV time error handling
/** @param {WeakSet<Error>} value */
const handled_errors = new WeakSet();
export let is_throwing_error = false;
// Used for controlling the flush of effects.
let scheduler_mode = FLUSH_MICROTASK;
// Used for handling scheduling
@ -230,7 +231,7 @@ export function check_dirtiness(reaction) {
}
/**
* @param {Error} error
* @param {unknown} error
* @param {Effect} effect
*/
function propagate_error(error, effect) {
@ -254,7 +255,7 @@ function propagate_error(error, effect) {
}
current = parent;
}
is_throwing_error = false;
throw error;
}
@ -268,30 +269,43 @@ function should_rethrow_error(effect) {
);
}
export function reset_is_throwing_error() {
is_throwing_error = false;
}
/**
* @param {unknown} error
* @param {Effect} effect
* @param {Effect | null} previous_effect
* @param {ComponentContext | null} component_context
*/
export function handle_error(error, effect, component_context) {
if (!(error instanceof Error)) {
throw error;
}
if (handled_errors.has(error)) {
export function handle_error(error, effect, previous_effect, component_context) {
if (is_throwing_error) {
if (previous_effect === null) {
is_throwing_error = false;
}
if (should_rethrow_error(effect)) {
throw error;
}
return;
}
handled_errors.add(error);
if (previous_effect !== null) {
is_throwing_error = true;
}
if (!DEV || component_context === null) {
if (
!DEV ||
component_context === null ||
!(error instanceof Error) ||
handled_errors.has(error)
) {
propagate_error(error, effect);
return;
}
handled_errors.add(error);
const component_stack = [];
const effect_name = effect.fn?.name;
@ -507,7 +521,7 @@ export function update_effect(effect) {
dev_effect_stack.push(effect);
}
} catch (error) {
handle_error(error, effect, previous_component_context || effect.ctx);
handle_error(error, effect, previous_effect, previous_component_context || effect.ctx);
} finally {
active_effect = previous_effect;
@ -608,7 +622,7 @@ function flush_queued_effects(effects) {
}
}
} catch (error) {
handle_error(error, effect, effect.ctx);
handle_error(error, effect, null, effect.ctx);
}
}
}
@ -688,7 +702,7 @@ function process_effects(effect, collected_effects) {
update_effect(current_effect);
}
} catch (error) {
handle_error(error, current_effect, current_effect.ctx);
handle_error(error, current_effect, null, current_effect.ctx);
}
}

@ -5,7 +5,7 @@
$effect.pre(() => {
if (count > 1) {
throw new Error('too high');
throw 'too high';
}
});
</script>

Loading…
Cancel
Save