diff --git a/.changeset/tangy-icons-dig.md b/.changeset/tangy-icons-dig.md
new file mode 100644
index 0000000000..6d87912bbb
--- /dev/null
+++ b/.changeset/tangy-icons-dig.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: unset context synchronously in `run`
diff --git a/packages/svelte/src/internal/client/reactivity/async.js b/packages/svelte/src/internal/client/reactivity/async.js
index c1d4cbcd67..12c5e9baa5 100644
--- a/packages/svelte/src/internal/client/reactivity/async.js
+++ b/packages/svelte/src/internal/client/reactivity/async.js
@@ -303,15 +303,21 @@ export function run(thunks) {
.then(() => {
restore();
- if (errored) {
- throw errored.error;
+ try {
+ if (errored) {
+ throw errored.error;
+ }
+
+ if (aborted(active)) {
+ throw STALE_REACTION;
+ }
+
+ return fn();
+ } finally {
+ // We gotta unset context directly in case the function returns a promise, in which case
+ // unset_context in .finally() would be too late ...
+ unset_context();
}
-
- if (aborted(active)) {
- throw STALE_REACTION;
- }
-
- return fn();
})
.catch(handle_error);
@@ -320,6 +326,7 @@ export function run(thunks) {
promise.finally(() => {
blocker.settled = true;
+ // ... but we also need it after such a promise has resolved in case it restores our context
unset_context();
});
}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/Child.svelte b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/Child.svelte
new file mode 100644
index 0000000000..6f84dc319e
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/Child.svelte
@@ -0,0 +1,7 @@
+
+
+{x} {y}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/_config.js b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/_config.js
new file mode 100644
index 0000000000..a0dc38c660
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/_config.js
@@ -0,0 +1,26 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ assert, target }) {
+ const [show, resolve, count] = target.querySelectorAll('button');
+
+ show.click();
+ await tick();
+ resolve.click();
+ await tick();
+ count.click();
+ await tick();
+ assert.htmlEqual(
+ target.innerHTML,
+ ' '
+ );
+
+ resolve.click();
+ await tick();
+ assert.htmlEqual(
+ target.innerHTML,
+ '1 2 '
+ );
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/main.svelte
new file mode 100644
index 0000000000..0a5346cc47
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-run-isolated-batch/main.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+{#if show}
+
+{/if}
+
+
+
+