Skip to content

Commit

Permalink
fix: restore active reaction if then block throws (#14191)
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloricciuti authored and trueadm committed Nov 7, 2024
1 parent 34f1475 commit 3006fc7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-doors-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: restore active reaction if then block throws
64 changes: 33 additions & 31 deletions packages/svelte/src/internal/client/dom/blocks/await.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,42 +70,44 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
if (DEV) set_dev_current_component_function(component_function);
}

if (state === PENDING && pending_fn) {
if (pending_effect) resume_effect(pending_effect);
else pending_effect = branch(() => pending_fn(anchor));
}

if (state === THEN && then_fn) {
if (then_effect) resume_effect(then_effect);
else then_effect = branch(() => then_fn(anchor, input_source));
}
try {
if (state === PENDING && pending_fn) {
if (pending_effect) resume_effect(pending_effect);
else pending_effect = branch(() => pending_fn(anchor));
}

if (state === CATCH && catch_fn) {
if (catch_effect) resume_effect(catch_effect);
else catch_effect = branch(() => catch_fn(anchor, error_source));
}
if (state === THEN && then_fn) {
if (then_effect) resume_effect(then_effect);
else then_effect = branch(() => then_fn(anchor, input_source));
}

if (state !== PENDING && pending_effect) {
pause_effect(pending_effect, () => (pending_effect = null));
}
if (state === CATCH && catch_fn) {
if (catch_effect) resume_effect(catch_effect);
else catch_effect = branch(() => catch_fn(anchor, error_source));
}

if (state !== THEN && then_effect) {
pause_effect(then_effect, () => (then_effect = null));
}
if (state !== PENDING && pending_effect) {
pause_effect(pending_effect, () => (pending_effect = null));
}

if (state !== CATCH && catch_effect) {
pause_effect(catch_effect, () => (catch_effect = null));
}
if (state !== THEN && then_effect) {
pause_effect(then_effect, () => (then_effect = null));
}

if (restore) {
if (DEV) set_dev_current_component_function(null);
set_component_context(null);
set_active_reaction(null);
set_active_effect(null);

// without this, the DOM does not update until two ticks after the promise
// resolves, which is unexpected behaviour (and somewhat irksome to test)
flush_sync();
if (state !== CATCH && catch_effect) {
pause_effect(catch_effect, () => (catch_effect = null));
}
} finally {
if (restore) {
if (DEV) set_dev_current_component_function(null);
set_component_context(null);
set_active_reaction(null);
set_active_effect(null);

// without this, the DOM does not update until two ticks after the promise
// resolves, which is unexpected behaviour (and somewhat irksome to test)
flush_sync();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ok, test } from '../../test';
import { flushSync } from 'svelte';

export default test({
compileOptions: {
dev: true
},
async test({ target, errors, assert, window }) {
const btn = target.querySelector('button');
ok(btn);
flushSync(() => {
btn.click();
});
assert.deepEqual(errors, []);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script>
let count = $state(0);
function listen(node){
function handler(){
count++;
}
node.addEventListener("click", handler);
return {
destroy(){
node.removeEventListener("click", handler);
}
}
}
</script>

<button use:listen></button>

{#await Promise.resolve() then}
{err.or}
{/await}

0 comments on commit 3006fc7

Please sign in to comment.