diff --git a/packages/svelte/src/internal/client/reactivity/async.js b/packages/svelte/src/internal/client/reactivity/async.js index 27828f401c..cd88f6e47e 100644 --- a/packages/svelte/src/internal/client/reactivity/async.js +++ b/packages/svelte/src/internal/client/reactivity/async.js @@ -1,5 +1,5 @@ /** @import { Effect, TemplateNode, Value } from '#client' */ -import { DESTROYED } from '#client/constants'; +import { DESTROYED, STALE_REACTION } from '#client/constants'; import { DEV } from 'esm-env'; import { component_context, @@ -290,15 +290,36 @@ export function run(thunks) { boundary.update_pending_count(1); batch.increment(blocking); + var active = /** @type {Effect} */ (active_effect); + + /** @type {null | { error: any }} */ + var errored = null; + let was_hydrating = hydrating; - var promise = Promise.resolve(thunks[0]()); + /** @param {any} error */ + const handle_error = (error) => { + errored = { error }; // wrap in object in case a promise rejects with a falsy value + + if (!aborted(active)) { + invoke_error_boundary(error, active); + } + }; + + var promise = Promise.resolve(thunks[0]()).catch(handle_error); + var promises = [promise]; for (const fn of thunks.slice(1)) { promise = promise .then(() => { - // TODO abort if component was destroyed? + if (errored) { + throw errored.error; + } + + if (aborted(active)) { + throw STALE_REACTION; + } try { restore(); @@ -312,7 +333,8 @@ export function run(thunks) { } } }) - .then(() => { + .catch(handle_error) + .finally(() => { unset_context(); if (was_hydrating) { diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-module/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived-module/_config.js index 318f88bcc9..5ab7a9aa8c 100644 --- a/packages/svelte/tests/runtime-runes/samples/async-derived-module/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-module/_config.js @@ -67,15 +67,15 @@ export default test({ assert.deepEqual(logs, [ 'outside boundary 1', - '$effect.pre 42 1', 'template 42 1', + '$effect.pre 42 1', '$effect 42 1', - '$effect.pre 84 2', 'template 84 2', + '$effect.pre 84 2', 'outside boundary 2', '$effect 84 2', - '$effect.pre 86 2', 'template 86 2', + '$effect.pre 86 2', '$effect 86 2' ]); } diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived/_config.js index 7239643464..a439b082e9 100644 --- a/packages/svelte/tests/runtime-runes/samples/async-derived/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/async-derived/_config.js @@ -33,15 +33,15 @@ export default test({ assert.deepEqual(logs, [ 'outside boundary 1', - '$effect.pre 1a 1', 'template 1a 1', + '$effect.pre 1a 1', '$effect 1a 1', - '$effect.pre 2a 2', 'template 2a 2', + '$effect.pre 2a 2', 'outside boundary 2', '$effect 2a 2', - '$effect.pre 2b 2', 'template 2b 2', + '$effect.pre 2b 2', '$effect 2b 2' ]); }