diff --git a/.changeset/silly-masks-exist.md b/.changeset/silly-masks-exist.md new file mode 100644 index 0000000000..e1b161719b --- /dev/null +++ b/.changeset/silly-masks-exist.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: prevent numerous transition/animation memory leaks diff --git a/packages/svelte/src/internal/client/dom/elements/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js index 5d0005b2c1..8777ba706b 100644 --- a/packages/svelte/src/internal/client/dom/elements/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -222,6 +222,8 @@ export function transition(flags, element, get_fn, get_params) { 1, () => { dispatch_event(element, 'introend'); + // Ensure we cancel the animation to prevent leaking + intro?.abort(); intro = current_options = undefined; }, is_both @@ -249,6 +251,8 @@ export function transition(flags, element, get_fn, get_params) { 0, () => { dispatch_event(element, 'outroend'); + // Ensure we cancel the animation to prevent leaking + outro?.abort(); outro = current_options = undefined; fn?.(); }, @@ -322,8 +326,10 @@ function animate(element, options, counterpart, t2, on_finish, on_abort) { // once DOM has been updated... /** @type {Animation} */ var a; + var aborted = false; queue_micro_task(() => { + if (aborted) return; var o = options({ direction: is_intro ? 'in' : 'out' }); a = animate(element, o, counterpart, t2, on_finish, on_abort); }); @@ -331,7 +337,10 @@ function animate(element, options, counterpart, t2, on_finish, on_abort) { // ...but we want to do so without using `async`/`await` everywhere, so // we return a facade that allows everything to remain synchronous return { - abort: () => a.abort(), + abort: () => { + aborted = true; + a?.abort(); + }, deactivate: () => a.deactivate(), reset: () => a.reset(), t: (now) => a.t(now) diff --git a/playgrounds/demo/index.html b/playgrounds/demo/index.html index fae74ccb1e..512b5426a9 100644 --- a/playgrounds/demo/index.html +++ b/playgrounds/demo/index.html @@ -20,9 +20,6 @@ const component = render(App, { target: document.getElementById('root') }); - - // @ts-ignore - window.unmount = () => unmount(component);