diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/this.js b/packages/svelte/src/internal/client/dom/elements/bindings/this.js index f2e715113f..45d87aa7bf 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/this.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/this.js @@ -1,5 +1,7 @@ import { STATE_SYMBOL } from '#client/constants'; +import { capture_signals } from '../../../legacy.js'; import { effect, render_effect } from '../../../reactivity/effects.js'; +import { old_values } from '../../../reactivity/sources.js'; import { untrack } from '../../../runtime.js'; import { queue_micro_task } from '../../task.js'; @@ -48,12 +50,16 @@ export function bind_this(element_or_component = {}, update, get_value, get_part }); return () => { - // We cannot use effects in the teardown phase, we we use a microtask instead. - queue_micro_task(() => { - if (parts && is_bound_this(get_value(...parts), element_or_component)) { - update(null, ...parts); - } - }); + const signals = capture_signals(get_value); + + if (parts && is_bound_this(get_value(...parts), element_or_component)) { + update(null, ...parts); + } + + if (signals && signals.size === 1) { + const [signal] = [...signals]; + old_values.set(signal, element_or_component); + } }; }); diff --git a/packages/svelte/src/internal/client/legacy.js b/packages/svelte/src/internal/client/legacy.js index 97ad7244c0..a086fd7d93 100644 --- a/packages/svelte/src/internal/client/legacy.js +++ b/packages/svelte/src/internal/client/legacy.js @@ -13,7 +13,7 @@ export let captured_signals = null; * @template T * @param {() => T} fn */ -function capture_signals(fn) { +export function capture_signals(fn) { var previous_captured_signals = captured_signals; try { diff --git a/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/Inner.svelte b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/Inner.svelte new file mode 100644 index 0000000000..e9e6e0d18d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/Inner.svelte @@ -0,0 +1,9 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/_config.js b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/_config.js new file mode 100644 index 0000000000..a0426cedbf --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/_config.js @@ -0,0 +1,15 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + ssrHtml: '
', + html: 'HELLO
', + + async test({ assert, target }) { + const [button] = target.querySelectorAll('button'); + + flushSync(() => button.click()); + + assert.htmlEqual(target.innerHTML, ''); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/main.svelte b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/main.svelte new file mode 100644 index 0000000000..11e75b8b6d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-block-const-destroyed-external-reader/main.svelte @@ -0,0 +1,19 @@ + + +{#if value} + {@const result = value} +{externalView}
diff --git a/packages/svelte/tests/runtime-runes/samples/if-block-const-inert-derived/_config.js b/packages/svelte/tests/runtime-runes/samples/if-block-const-inert-derived/_config.js new file mode 100644 index 0000000000..b803182079 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-block-const-inert-derived/_config.js @@ -0,0 +1,18 @@ +import { flushSync, tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: 'hello
{result.data}
+