diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js index 72157eaa40..bad3c726b9 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js @@ -1,7 +1,10 @@ /** @import { TemplateNode, Dom, Effect } from '#client' */ import { EFFECT_TRANSPARENT } from '../../constants.js'; import { block, branch, pause_effect } from '../../reactivity/effects.js'; +import { active_effect } from '../../runtime.js'; import { hydrate_next, hydrate_node, hydrating } from '../hydration.js'; +import { should_defer_append } from '../operations.js'; +import { add_boundary_callback, find_boundary } from './boundary.js'; /** * @template P @@ -24,16 +27,47 @@ export function component(node, get_component, render_fn) { /** @type {Effect | null} */ var effect; - block(() => { - if (component === (component = get_component())) return; + /** @type {DocumentFragment | null} */ + var offscreen_fragment = null; + + /** @type {Effect | null} */ + var pending_effect = null; + var boundary = find_boundary(active_effect); + + function commit() { if (effect) { pause_effect(effect); effect = null; } + if (offscreen_fragment) { + anchor.before(offscreen_fragment); + offscreen_fragment = null; + } + + effect = pending_effect; + } + + block(() => { + if (component === (component = get_component())) return; + if (component) { - effect = branch(() => render_fn(anchor, component)); + var defer = boundary !== null && should_defer_append(); + var target = anchor; + + if (defer) { + offscreen_fragment = document.createDocumentFragment(); + offscreen_fragment.append((target = document.createComment(''))); + } + + pending_effect = branch(() => render_fn(anchor, component)); + + if (defer) { + add_boundary_callback(boundary, commit); + } else { + commit(); + } } }, EFFECT_TRANSPARENT);