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
pull/16573/head
Simon H 4 weeks ago committed by GitHub
parent d2ba2589fe
commit 0480f040c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: skip effects inside dynamic component that is about to be destroyed

@ -62,8 +62,10 @@ export function component(node, get_component, render_fn) {
if (defer) {
offscreen_fragment = document.createDocumentFragment();
offscreen_fragment.append((target = create_text()));
if (effect) {
/** @type {Batch} */ (current_batch).skipped_effects.add(effect);
}
}
pending_effect = branch(() => render_fn(target, component));
}

@ -0,0 +1,7 @@
<script>
let { data } = $props();
</script>
{#each data.obj.arr as i}
<p>{i}</p>
{/each}

@ -0,0 +1,11 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
const [btn] = target.querySelectorAll('button');
btn.click();
flushSync();
assert.htmlEqual(target.innerHTML, `<button>Change</button> <p>Comp 2</p>`);
}
});

@ -0,0 +1,16 @@
<script>
import Comp_1 from './Comp-1.svelte';
import Comp_2 from './Comp-2.svelte';
let Comp = $state.raw(Comp_1);
let data = $state.raw({ obj: { arr: [1, 2, 3] } });
function change() {
Comp = Comp_2;
data = {};
}
</script>
<button onclick={change}>Change</button>
<Comp {data} />
Loading…
Cancel
Save