From 0b3fd4e42d1766bc7d4b8c24d2443de124555375 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 24 Sep 2024 17:16:07 +0100 Subject: [PATCH] fix: properly remove root anchor node on unmount (#13381) --- .changeset/tasty-mice-admire.md | 5 ++++ packages/svelte/src/internal/client/render.js | 14 +++++++---- .../mount-unmount-anchor/Component.svelte | 5 ++++ .../samples/mount-unmount-anchor/_config.js | 23 +++++++++++++++++++ .../samples/mount-unmount-anchor/main.svelte | 20 ++++++++++++++++ 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 .changeset/tasty-mice-admire.md create mode 100644 packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/Component.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/main.svelte diff --git a/.changeset/tasty-mice-admire.md b/.changeset/tasty-mice-admire.md new file mode 100644 index 0000000000..f16687a7d3 --- /dev/null +++ b/.changeset/tasty-mice-admire.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: properly remove root anchor node on unmount diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 72083cd4e8..de986ae04e 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -81,8 +81,7 @@ export function set_text(text, value) { * @returns {Exports} */ export function mount(component, options) { - const anchor = options.anchor ?? options.target.appendChild(create_text()); - return _mount(component, { ...options, anchor }); + return _mount(component, options); } /** @@ -176,7 +175,7 @@ const document_listeners = new Map(); * @param {ComponentType> | Component} Component * @param {{ * target: Document | Element | ShadowRoot; - * anchor: Node; + * anchor?: Node; * props?: any; * events?: any; * context?: Map; @@ -225,6 +224,8 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro var component = undefined; var unmount = effect_root(() => { + var anchor_node = anchor ?? target.appendChild(create_text()); + branch(() => { if (context) { push({}); @@ -238,12 +239,12 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro } if (hydrating) { - assign_nodes(/** @type {TemplateNode} */ (anchor), null); + assign_nodes(/** @type {TemplateNode} */ (anchor_node), null); } should_intro = intro; // @ts-expect-error the public typings are not what the actual function looks like - component = Component(anchor, props) || {}; + component = Component(anchor_node, props) || {}; should_intro = true; if (hydrating) { @@ -271,6 +272,9 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro root_event_handles.delete(event_handle); mounted_components.delete(component); + if (anchor_node !== anchor) { + anchor_node.parentNode?.removeChild(anchor_node); + } }; }); diff --git a/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/Component.svelte b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/Component.svelte new file mode 100644 index 0000000000..d348f94eb1 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/Component.svelte @@ -0,0 +1,5 @@ + + +

{text}

diff --git a/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/_config.js b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/_config.js new file mode 100644 index 0000000000..9755112938 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/_config.js @@ -0,0 +1,23 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + test({ assert, target }) { + const btn = target.querySelector('button'); + btn?.click(); + flushSync(); + btn?.click(); + flushSync(); + btn?.click(); + flushSync(); + btn?.click(); + flushSync(); + btn?.click(); + flushSync(); + + const div = target.querySelector('div'); + + assert.htmlEqual(target.innerHTML, '
'); + assert.equal(div?.childNodes.length, 0); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/main.svelte b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/main.svelte new file mode 100644 index 0000000000..8bb53a3907 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/mount-unmount-anchor/main.svelte @@ -0,0 +1,20 @@ + + + +