Skip to content

Commit 44a833f

Browse files
fix: restore active reaction if then block throws (#14191)
1 parent f1aeaf1 commit 44a833f

File tree

4 files changed

+75
-31
lines changed

4 files changed

+75
-31
lines changed

.changeset/pink-doors-chew.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: restore active reaction if then block throws

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

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -70,42 +70,44 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
7070
if (DEV) set_dev_current_component_function(component_function);
7171
}
7272

73-
if (state === PENDING && pending_fn) {
74-
if (pending_effect) resume_effect(pending_effect);
75-
else pending_effect = branch(() => pending_fn(anchor));
76-
}
77-
78-
if (state === THEN && then_fn) {
79-
if (then_effect) resume_effect(then_effect);
80-
else then_effect = branch(() => then_fn(anchor, input_source));
81-
}
73+
try {
74+
if (state === PENDING && pending_fn) {
75+
if (pending_effect) resume_effect(pending_effect);
76+
else pending_effect = branch(() => pending_fn(anchor));
77+
}
8278

83-
if (state === CATCH && catch_fn) {
84-
if (catch_effect) resume_effect(catch_effect);
85-
else catch_effect = branch(() => catch_fn(anchor, error_source));
86-
}
79+
if (state === THEN && then_fn) {
80+
if (then_effect) resume_effect(then_effect);
81+
else then_effect = branch(() => then_fn(anchor, input_source));
82+
}
8783

88-
if (state !== PENDING && pending_effect) {
89-
pause_effect(pending_effect, () => (pending_effect = null));
90-
}
84+
if (state === CATCH && catch_fn) {
85+
if (catch_effect) resume_effect(catch_effect);
86+
else catch_effect = branch(() => catch_fn(anchor, error_source));
87+
}
9188

92-
if (state !== THEN && then_effect) {
93-
pause_effect(then_effect, () => (then_effect = null));
94-
}
89+
if (state !== PENDING && pending_effect) {
90+
pause_effect(pending_effect, () => (pending_effect = null));
91+
}
9592

96-
if (state !== CATCH && catch_effect) {
97-
pause_effect(catch_effect, () => (catch_effect = null));
98-
}
93+
if (state !== THEN && then_effect) {
94+
pause_effect(then_effect, () => (then_effect = null));
95+
}
9996

100-
if (restore) {
101-
if (DEV) set_dev_current_component_function(null);
102-
set_component_context(null);
103-
set_active_reaction(null);
104-
set_active_effect(null);
105-
106-
// without this, the DOM does not update until two ticks after the promise
107-
// resolves, which is unexpected behaviour (and somewhat irksome to test)
108-
flush_sync();
97+
if (state !== CATCH && catch_effect) {
98+
pause_effect(catch_effect, () => (catch_effect = null));
99+
}
100+
} finally {
101+
if (restore) {
102+
if (DEV) set_dev_current_component_function(null);
103+
set_component_context(null);
104+
set_active_reaction(null);
105+
set_active_effect(null);
106+
107+
// without this, the DOM does not update until two ticks after the promise
108+
// resolves, which is unexpected behaviour (and somewhat irksome to test)
109+
flush_sync();
110+
}
109111
}
110112
}
111113

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ok, test } from '../../test';
2+
import { flushSync } from 'svelte';
3+
4+
export default test({
5+
compileOptions: {
6+
dev: true
7+
},
8+
async test({ target, errors, assert, window }) {
9+
const btn = target.querySelector('button');
10+
ok(btn);
11+
flushSync(() => {
12+
btn.click();
13+
});
14+
assert.deepEqual(errors, []);
15+
}
16+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script>
2+
let count = $state(0);
3+
4+
function listen(node){
5+
function handler(){
6+
count++;
7+
}
8+
node.addEventListener("click", handler);
9+
return {
10+
destroy(){
11+
node.removeEventListener("click", handler);
12+
}
13+
}
14+
}
15+
</script>
16+
17+
<button use:listen></button>
18+
19+
{#await Promise.resolve() then}
20+
{err.or}
21+
{/await}

0 commit comments

Comments
 (0)