From 0d7ba6ab26b241e678caa202927a6d66ed57dedd Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 29 Nov 2023 14:20:08 +0000 Subject: [PATCH 1/6] chore: remove redundant hydration code chore: remove redundant hydration code --- .changeset/sour-forks-stare.md | 5 +++++ packages/svelte/src/internal/client/hydration.js | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 .changeset/sour-forks-stare.md diff --git a/.changeset/sour-forks-stare.md b/.changeset/sour-forks-stare.md new file mode 100644 index 000000000000..7bdd4433c4d8 --- /dev/null +++ b/.changeset/sour-forks-stare.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: remove redundant hydration code diff --git a/packages/svelte/src/internal/client/hydration.js b/packages/svelte/src/internal/client/hydration.js index dfd850c96772..df0bdb6b3e10 100644 --- a/packages/svelte/src/internal/client/hydration.js +++ b/packages/svelte/src/internal/client/hydration.js @@ -68,12 +68,11 @@ export function hydrate_block_anchor(anchor_node, is_controlled) { let fragment = target_node.$$fragment; if (fragment === undefined) { fragment = get_hydration_fragment(target_node); - // @ts-ignore remove to prevent memory leaks - target_node.$$fragment = undefined; } set_current_hydration_fragment(fragment); } else { - set_current_hydration_fragment([/** @type {Element} */ (target_node.firstChild)]); + const firstChild = /** @type {Element | null} */ (target_node.firstChild); + set_current_hydration_fragment(firstChild === null ? [] : [firstChild]); } } } From bb67f1cac7ece066d5a77f0d279535e673958ac0 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 29 Nov 2023 14:34:02 +0000 Subject: [PATCH 2/6] cleanup --- packages/svelte/src/internal/client/render.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 21390fa4e021..607c7f3dedfa 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -1396,9 +1396,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) { } else if (current_hydration_fragment !== null) { const comment_text = /** @type {Comment} */ (current_hydration_fragment?.[0])?.data; if ( - (!comment_text && - // Can happen when a svelte:element that is turned into a void element has an if block inside - current_hydration_fragment[0] !== null) || + !comment_text || (comment_text === 'ssr:if:true' && !result) || (comment_text === 'ssr:if:false' && result) ) { From c77b0e8e40cd3c9b893d5213a0e2e68c18410e5b Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 29 Nov 2023 14:38:17 +0000 Subject: [PATCH 3/6] lint --- packages/svelte/src/internal/client/hydration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/internal/client/hydration.js b/packages/svelte/src/internal/client/hydration.js index df0bdb6b3e10..a306a987c87b 100644 --- a/packages/svelte/src/internal/client/hydration.js +++ b/packages/svelte/src/internal/client/hydration.js @@ -71,8 +71,8 @@ export function hydrate_block_anchor(anchor_node, is_controlled) { } set_current_hydration_fragment(fragment); } else { - const firstChild = /** @type {Element | null} */ (target_node.firstChild); - set_current_hydration_fragment(firstChild === null ? [] : [firstChild]); + const first_child = /** @type {Element | null} */ (target_node.firstChild); + set_current_hydration_fragment(first_child === null ? [] : [first_child]); } } } From 5b5df3dbd29c5fe8f305d3d0857d35b0e2038976 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 29 Nov 2023 15:42:33 +0000 Subject: [PATCH 4/6] cleanup memory --- packages/svelte/src/internal/client/render.js | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 607c7f3dedfa..c646a3e2d991 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -61,8 +61,7 @@ import { push, current_component_context, pop, - schedule_task, - managed_render_effect + schedule_task } from './runtime.js'; import { current_hydration_fragment, @@ -199,7 +198,7 @@ export function comment(anchor) { /** * @param {Element | Text} dom * @param {boolean} is_fragment - * @param {null | Text | Comment | Element} anchor + * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor * @returns {void} */ function close_template(dom, is_fragment, anchor) { @@ -211,14 +210,18 @@ function close_template(dom, is_fragment, anchor) { ? dom : /** @type {import('./types.js').TemplateNode[]} */ (Array.from(dom.childNodes)) : dom; - if (anchor !== null && current_hydration_fragment === null) { - insert(current, null, anchor); + if (anchor !== null) { + if (current_hydration_fragment === null) { + insert(current, null, anchor); + } else { + cleanup_hyration_node(anchor); + } } block.d = current; } /** - * @param {null | Text | Comment | Element} anchor + * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor * @param {Element | Text} dom * @returns {void} */ @@ -227,7 +230,7 @@ export function close(anchor, dom) { } /** - * @param {null | Text | Comment | Element} anchor + * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor * @param {Element | Text} dom * @returns {void} */ @@ -1341,6 +1344,20 @@ export function slot(anchor_node, slot_fn, slot_props, fallback_fn) { } else { slot_fn(anchor_node, slot_props); } + cleanup_hyration_node(anchor_node); +} + +/** + * + * @param {Element | Comment} node + */ +function cleanup_hyration_node(node) { + // Let's ensure we don't leak the hydration fragment + // @ts-expect-error internal field + if (node.$$fragment) { + // @ts-expect-error internal field + node.$$fragment = undefined; + } } /** @@ -1472,6 +1489,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) { destroy_signal(alternate_effect); }); block.e = if_effect; + cleanup_hyration_node(anchor_node); } export { if_block as if }; @@ -1615,6 +1633,7 @@ export function element(anchor_node, tag_fn, render_fn, is_svg = false) { } destroy_signal(render_effect_signal); }); + cleanup_hyration_node(anchor_node); block.e = element_effect; } @@ -1732,6 +1751,7 @@ export function component(anchor_node, component_fn, render_fn) { render = render.p; } }); + cleanup_hyration_node(anchor_node); block.e = component_effect; } @@ -1899,6 +1919,7 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) { render = render.p; } }); + cleanup_hyration_node(anchor_node); block.e = await_effect; } export { await_block as await }; @@ -2015,6 +2036,7 @@ export function key(anchor_node, key, render_fn) { render = render.p; } }); + cleanup_hyration_node(anchor_node); block.e = key_effect; } @@ -2270,6 +2292,7 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re reconcile_fn([], block, anchor_node, is_controlled, render_fn, flags, false, keys); destroy_signal(/** @type {import('./types.js').EffectSignal} */ (render)); }); + cleanup_hyration_node(anchor_node); block.e = each; } From 8392fa0881edb30d037d88e6f2c817bd5e3bc626 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 29 Nov 2023 15:49:48 +0000 Subject: [PATCH 5/6] ts --- packages/svelte/src/internal/client/render.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index c646a3e2d991..f41f0438fbfe 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -198,7 +198,7 @@ export function comment(anchor) { /** * @param {Element | Text} dom * @param {boolean} is_fragment - * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor + * @param {null | Text | Comment | Element} anchor * @returns {void} */ function close_template(dom, is_fragment, anchor) { @@ -221,7 +221,7 @@ function close_template(dom, is_fragment, anchor) { } /** - * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor + * @param {null | Text | Comment | Element} anchor * @param {Element | Text} dom * @returns {void} */ @@ -230,7 +230,7 @@ export function close(anchor, dom) { } /** - * @param {null | ((Text | Comment | Element) & {$$fragment: undefined | Node[]})} anchor + * @param {null | Text | Comment | Element} anchor * @param {Element | Text} dom * @returns {void} */ From 317de4abbf49e9a7e0b9fa380f5d106d9ef47007 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 30 Nov 2023 10:08:17 +0000 Subject: [PATCH 6/6] alternative approach --- .../svelte/src/internal/client/hydration.js | 7 ++++++ packages/svelte/src/internal/client/render.js | 22 ------------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/packages/svelte/src/internal/client/hydration.js b/packages/svelte/src/internal/client/hydration.js index a306a987c87b..ea7eac73f4bb 100644 --- a/packages/svelte/src/internal/client/hydration.js +++ b/packages/svelte/src/internal/client/hydration.js @@ -1,5 +1,7 @@ // Handle hydration +import { schedule_task } from './runtime'; + /** @type {null | Array} */ export let current_hydration_fragment = null; @@ -68,6 +70,11 @@ export function hydrate_block_anchor(anchor_node, is_controlled) { let fragment = target_node.$$fragment; if (fragment === undefined) { fragment = get_hydration_fragment(target_node); + } else { + schedule_task(() => { + // @ts-expect-error clean up memory + target_node.$$fragment = undefined; + }); } set_current_hydration_fragment(fragment); } else { diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index f41f0438fbfe..79a891acd6a0 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -213,8 +213,6 @@ function close_template(dom, is_fragment, anchor) { if (anchor !== null) { if (current_hydration_fragment === null) { insert(current, null, anchor); - } else { - cleanup_hyration_node(anchor); } } block.d = current; @@ -1344,20 +1342,6 @@ export function slot(anchor_node, slot_fn, slot_props, fallback_fn) { } else { slot_fn(anchor_node, slot_props); } - cleanup_hyration_node(anchor_node); -} - -/** - * - * @param {Element | Comment} node - */ -function cleanup_hyration_node(node) { - // Let's ensure we don't leak the hydration fragment - // @ts-expect-error internal field - if (node.$$fragment) { - // @ts-expect-error internal field - node.$$fragment = undefined; - } } /** @@ -1489,7 +1473,6 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) { destroy_signal(alternate_effect); }); block.e = if_effect; - cleanup_hyration_node(anchor_node); } export { if_block as if }; @@ -1633,7 +1616,6 @@ export function element(anchor_node, tag_fn, render_fn, is_svg = false) { } destroy_signal(render_effect_signal); }); - cleanup_hyration_node(anchor_node); block.e = element_effect; } @@ -1751,7 +1733,6 @@ export function component(anchor_node, component_fn, render_fn) { render = render.p; } }); - cleanup_hyration_node(anchor_node); block.e = component_effect; } @@ -1919,7 +1900,6 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) { render = render.p; } }); - cleanup_hyration_node(anchor_node); block.e = await_effect; } export { await_block as await }; @@ -2036,7 +2016,6 @@ export function key(anchor_node, key, render_fn) { render = render.p; } }); - cleanup_hyration_node(anchor_node); block.e = key_effect; } @@ -2292,7 +2271,6 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re reconcile_fn([], block, anchor_node, is_controlled, render_fn, flags, false, keys); destroy_signal(/** @type {import('./types.js').EffectSignal} */ (render)); }); - cleanup_hyration_node(anchor_node); block.e = each; }