diff --git a/.changeset/cyan-spies-grin.md b/.changeset/cyan-spies-grin.md new file mode 100644 index 0000000000..b278b427b6 --- /dev/null +++ b/.changeset/cyan-spies-grin.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: improve global transition handling of effect cleardown diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 458f4ec684..f9be124243 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -1765,7 +1765,9 @@ export function component(anchor_node, component_fn, render_fn) { transition.f(() => { transitions.delete(transition); if (transitions.size === 0) { - if (render.e !== null) { + // If the current render has changed since, then we can remove the old render + // effect as it's stale. + if (current_render !== render && render.e !== null) { if (render.d !== null) { remove(render.d); render.d = null; @@ -1891,7 +1893,9 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) { transition.f(() => { transitions.delete(transition); if (transitions.size === 0) { - if (render.e !== null) { + // If the current render has changed since, then we can remove the old render + // effect as it's stale. + if (current_render !== render && render.e !== null) { if (render.d !== null) { remove(render.d); render.d = null; @@ -2051,7 +2055,9 @@ export function key(anchor_node, key, render_fn) { transition.f(() => { transitions.delete(transition); if (transitions.size === 0) { - if (render.e !== null) { + // If the current render has changed since, then we can remove the old render + // effect as it's stale. + if (current_render !== render && render.e !== null) { if (render.d !== null) { remove(render.d); render.d = null; diff --git a/packages/svelte/tests/animation-helpers.js b/packages/svelte/tests/animation-helpers.js index 880442244e..94bb1839a0 100644 --- a/packages/svelte/tests/animation-helpers.js +++ b/packages/svelte/tests/animation-helpers.js @@ -70,7 +70,11 @@ class Animation { _update() { if (this.#reversed) { - this.currentTime = this.#timeline_offset + (this.#timeline_offset - raf.time); + if (this.#timeline_offset === 0) { + this.currentTime = this.#duration - raf.time; + } else { + this.currentTime = this.#timeline_offset + (this.#timeline_offset - raf.time); + } } else { this.currentTime = raf.time - this.#timeline_offset; } @@ -130,6 +134,9 @@ class Animation { } reverse() { + if (this.#paused && !raf.animations.has(this)) { + raf.animations.add(this); + } this.#timeline_offset = this.currentTime; this.#reversed = !this.#reversed; this.playState = 'running'; diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/Component.svelte b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/Component.svelte new file mode 100644 index 0000000000..ae5ddd2d6a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/Component.svelte @@ -0,0 +1,10 @@ + + +

Outside

+ +{#if show} + +{/if} diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/_config.js b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/_config.js new file mode 100644 index 0000000000..f80737e8eb --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/_config.js @@ -0,0 +1,20 @@ +import { test } from '../../test'; +import { flushSync } from 'svelte'; + +export default test({ + async test({ assert, target, raf }) { + const btn = target.querySelector('button'); + + raf.tick(0); + + flushSync(() => { + btn?.click(); + }); + + assert.htmlEqual(target.innerHTML, `

Outside

`); + + raf.tick(100); + + assert.htmlEqual(target.innerHTML, `

Outside

`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/main.svelte b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/main.svelte new file mode 100644 index 0000000000..a59a6bd93f --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-component-transition/main.svelte @@ -0,0 +1,5 @@ + + +