From 8f4017a506ae51cdc1ec3c03f11de18dddd447d0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 12 Mar 2024 09:35:56 -0400 Subject: [PATCH] move code --- packages/svelte/src/internal/client/block.js | 16 -- .../client/dom/blocks/svelte-component.js | 147 ++++++++++++++++++ packages/svelte/src/internal/client/render.js | 120 -------------- packages/svelte/src/internal/index.js | 1 + 4 files changed, 148 insertions(+), 136 deletions(-) create mode 100644 packages/svelte/src/internal/client/dom/blocks/svelte-component.js diff --git a/packages/svelte/src/internal/client/block.js b/packages/svelte/src/internal/client/block.js index e71cdc7ec7..aa6f3fbd42 100644 --- a/packages/svelte/src/internal/client/block.js +++ b/packages/svelte/src/internal/client/block.js @@ -60,22 +60,6 @@ export function create_dynamic_element_block() { }; } -/** @returns {import('./types.js').DynamicComponentBlock} */ -export function create_dynamic_component_block() { - return { - // dom - d: null, - // effect - e: null, - // parent - p: /** @type {import('./types.js').Block} */ (current_block), - // transition - r: null, - // type - t: DYNAMIC_COMPONENT_BLOCK - }; -} - /** @returns {import('./types.js').SnippetBlock} */ export function create_snippet_block() { return { diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js new file mode 100644 index 0000000000..aee3a07130 --- /dev/null +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js @@ -0,0 +1,147 @@ +import { DYNAMIC_COMPONENT_BLOCK } from '../../constants.js'; +import { hydrate_block_anchor } from '../../hydration.js'; +import { destroy_effect, render_effect } from '../../reactivity/effects.js'; +import { remove } from '../../reconciler.js'; +import { current_block, execute_effect } from '../../runtime.js'; +import { trigger_transitions } from '../../transitions.js'; + +/** + * @template P + * @param {Comment} anchor_node + * @param {() => (props: P) => void} component_fn + * @param {(component: (props: P) => void) => void} render_fn + * @returns {void} + */ +export function component(anchor_node, component_fn, render_fn) { + /** @type {import('#client').DynamicComponentBlock} */ + const block = { + // dom + d: null, + // effect + e: null, + // parent + p: /** @type {import('#client').Block} */ (current_block), + // transition + r: null, + // type + t: DYNAMIC_COMPONENT_BLOCK + }; + + /** @type {null | import('#client').Render} */ + let current_render = null; + hydrate_block_anchor(anchor_node); + + /** @type {null | ((props: P) => void)} */ + let component = null; + + block.r = + /** + * @param {import('#client').Transition} transition + * @returns {void} + */ + (transition) => { + const render = /** @type {import('#client').Render} */ (current_render); + const transitions = render.s; + transitions.add(transition); + transition.f(() => { + transitions.delete(transition); + if (transitions.size === 0) { + // 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; + } + destroy_effect(render.e); + render.e = null; + } + } + }); + }; + + const create_render_effect = () => { + /** @type {import('#client').Render} */ + const render = { + d: null, + e: null, + s: new Set(), + p: current_render + }; + + // Managed effect + render.e = render_effect( + () => { + const current = block.d; + if (current !== null) { + remove(current); + block.d = null; + } + if (component) { + render_fn(component); + } + render.d = block.d; + block.d = null; + }, + block, + true + ); + + current_render = render; + }; + + const render = () => { + const render = current_render; + + if (render === null) { + create_render_effect(); + return; + } + + const transitions = render.s; + + if (transitions.size === 0) { + if (render.d !== null) { + remove(render.d); + render.d = null; + } + if (render.e) { + execute_effect(render.e); + } else { + create_render_effect(); + } + } else { + create_render_effect(); + trigger_transitions(transitions, 'out'); + } + }; + + const component_effect = render_effect( + () => { + const next_component = component_fn(); + if (component !== next_component) { + component = next_component; + render(); + } + }, + block, + false + ); + + component_effect.ondestroy = () => { + let render = current_render; + while (render !== null) { + const dom = render.d; + if (dom !== null) { + remove(dom); + } + const effect = render.e; + if (effect !== null) { + destroy_effect(effect); + } + render = render.p; + } + }; + + block.e = component_effect; +} diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index f21d9729b6..c8b53ebbcc 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -14,7 +14,6 @@ import { create_root_block, create_dynamic_element_block, create_head_block, - create_dynamic_component_block, create_snippet_block } from './block.js'; import { @@ -1676,125 +1675,6 @@ export function element(anchor_node, tag_fn, is_svg, render_fn) { block.e = element_effect; } -/** - * @template P - * @param {Comment} anchor_node - * @param {() => (props: P) => void} component_fn - * @param {(component: (props: P) => void) => void} render_fn - * @returns {void} - */ -export function component(anchor_node, component_fn, render_fn) { - const block = create_dynamic_component_block(); - - /** @type {null | import('./types.js').Render} */ - let current_render = null; - hydrate_block_anchor(anchor_node); - - /** @type {null | ((props: P) => void)} */ - let component = null; - block.r = - /** - * @param {import('./types.js').Transition} transition - * @returns {void} - */ - (transition) => { - const render = /** @type {import('./types.js').Render} */ (current_render); - const transitions = render.s; - transitions.add(transition); - transition.f(() => { - transitions.delete(transition); - if (transitions.size === 0) { - // 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; - } - destroy_effect(render.e); - render.e = null; - } - } - }); - }; - const create_render_effect = () => { - /** @type {import('./types.js').Render} */ - const render = { - d: null, - e: null, - s: new Set(), - p: current_render - }; - // Managed effect - const effect = render_effect( - () => { - const current = block.d; - if (current !== null) { - remove(current); - block.d = null; - } - if (component) { - render_fn(component); - } - render.d = block.d; - block.d = null; - }, - block, - true - ); - render.e = effect; - current_render = render; - }; - const render = () => { - const render = current_render; - if (render === null) { - create_render_effect(); - return; - } - const transitions = render.s; - if (transitions.size === 0) { - if (render.d !== null) { - remove(render.d); - render.d = null; - } - if (render.e) { - execute_effect(render.e); - } else { - create_render_effect(); - } - } else { - create_render_effect(); - trigger_transitions(transitions, 'out'); - } - }; - const component_effect = render_effect( - () => { - const next_component = component_fn(); - if (component !== next_component) { - component = next_component; - render(); - } - }, - block, - false - ); - component_effect.ondestroy = () => { - let render = current_render; - while (render !== null) { - const dom = render.d; - if (dom !== null) { - remove(dom); - } - const effect = render.e; - if (effect !== null) { - destroy_effect(effect); - } - render = render.p; - } - }; - block.e = component_effect; -} - /** * @param {Element | Text | Comment} anchor * @param {boolean} is_html diff --git a/packages/svelte/src/internal/index.js b/packages/svelte/src/internal/index.js index 1503477eb5..8de36d7f23 100644 --- a/packages/svelte/src/internal/index.js +++ b/packages/svelte/src/internal/index.js @@ -25,6 +25,7 @@ export { await_block as await } from './client/dom/blocks/await.js'; export { if_block as if } from './client/dom/blocks/if.js'; export { key_block as key } from './client/dom/blocks/key.js'; export * from './client/dom/blocks/each.js'; +export * from './client/dom/blocks/svelte-component.js'; export * from './client/reactivity/deriveds.js'; export * from './client/reactivity/effects.js'; export * from './client/reactivity/sources.js';