Skip to content

Commit 0480f04

Browse files
authored
fix: skip effects inside dynamic component that is about to be destroyed (#16601)
* fix: skip effects inside dynamic component that is about to be destroyed When a dynamic component was updated to a different instance and its props were updated at the same time, effects inside the component were still called with the already-changed props. The fix is to mark the branch as skipped to never got to those effects. Fixes #16387 * undo accidental commit
1 parent d2ba258 commit 0480f04

File tree

6 files changed

+43
-1
lines changed

6 files changed

+43
-1
lines changed

.changeset/neat-files-do.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: skip effects inside dynamic component that is about to be destroyed

packages/svelte/src/internal/client/dom/blocks/svelte-component.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ export function component(node, get_component, render_fn) {
6262
if (defer) {
6363
offscreen_fragment = document.createDocumentFragment();
6464
offscreen_fragment.append((target = create_text()));
65+
if (effect) {
66+
/** @type {Batch} */ (current_batch).skipped_effects.add(effect);
67+
}
6568
}
66-
6769
pending_effect = branch(() => render_fn(target, component));
6870
}
6971

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let { data } = $props();
3+
</script>
4+
5+
{#each data.obj.arr as i}
6+
<p>{i}</p>
7+
{/each}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Comp 2</p>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
const [btn] = target.querySelectorAll('button');
7+
btn.click();
8+
flushSync();
9+
assert.htmlEqual(target.innerHTML, `<button>Change</button> <p>Comp 2</p>`);
10+
}
11+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script>
2+
import Comp_1 from './Comp-1.svelte';
3+
import Comp_2 from './Comp-2.svelte';
4+
5+
let Comp = $state.raw(Comp_1);
6+
let data = $state.raw({ obj: { arr: [1, 2, 3] } });
7+
8+
function change() {
9+
Comp = Comp_2;
10+
data = {};
11+
}
12+
</script>
13+
14+
<button onclick={change}>Change</button>
15+
16+
<Comp {data} />

0 commit comments

Comments
 (0)