From 6143f6a6e3700a44940cfa458977961b103c0034 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 22 Mar 2024 11:34:01 -0400 Subject: [PATCH] attach DOM to effects --- .../svelte/src/internal/client/dom/blocks/key.js | 6 +----- .../client/dom/blocks/svelte-component.js | 6 +----- .../internal/client/dom/blocks/svelte-element.js | 11 +++++++---- .../src/internal/client/dom/blocks/svelte-head.js | 15 +++++++++------ .../svelte/src/internal/client/dom/template.js | 3 ++- .../src/internal/client/reactivity/effects.js | 1 + .../src/internal/client/reactivity/types.d.ts | 3 ++- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/blocks/key.js b/packages/svelte/src/internal/client/dom/blocks/key.js index f7cb9c6dee..a914fb172c 100644 --- a/packages/svelte/src/internal/client/dom/blocks/key.js +++ b/packages/svelte/src/internal/client/dom/blocks/key.js @@ -57,9 +57,6 @@ export function key_block(anchor, get_key, render_fn) { true ); - // @ts-expect-error TODO tidy up - effect.d = block.d; - effects.add(effect); } }, @@ -69,8 +66,7 @@ export function key_block(anchor, get_key, render_fn) { key_effect.ondestroy = () => { for (const e of effects) { - // @ts-expect-error TODO tidy up. ondestroy should be totally unnecessary - if (e.d) remove(e.d); + if (e.dom) remove(e.dom); } }; } 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 86fc548f04..3204e4eb0d 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js @@ -60,9 +60,6 @@ export function component(anchor, get_component, render_fn) { true ); - // @ts-expect-error TODO tidy up - effect.d = block.d; - effects.add(effect); } }, @@ -72,8 +69,7 @@ export function component(anchor, get_component, render_fn) { component_effect.ondestroy = () => { for (const e of effects) { - // @ts-expect-error TODO tidy up. ondestroy should be totally unnecessary - if (e.d) remove(e.d); + if (e.dom) remove(e.dom); } }; } diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js index bfaa47e844..f84cd12d23 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js @@ -12,16 +12,17 @@ import { is_array } from '../../utils.js'; import { set_should_intro } from '../../render.js'; import { current_each_item_block, set_current_each_item_block } from './each.js'; import { create_block } from './utils.js'; -import { current_block } from '../../runtime.js'; +import { current_block, current_effect } from '../../runtime.js'; /** * @param {import('#client').Block} block + * @param {import('#client').Effect} effect * @param {Element} from * @param {Element} to * @returns {void} */ -function swap_block_dom(block, from, to) { - const dom = block.d; +function swap_block_dom(block, effect, from, to) { + const dom = effect.dom; if (is_array(dom)) { for (let i = 0; i < dom.length; i++) { if (dom[i] === from) { @@ -31,6 +32,7 @@ function swap_block_dom(block, from, to) { } } else if (dom === from) { block.d = to; + effect.dom = to; } } @@ -42,6 +44,7 @@ function swap_block_dom(block, from, to) { * @returns {void} */ export function element(anchor, get_tag, is_svg, render_fn) { + const parent_effect = /** @type {import('#client').Effect} */ (current_effect); const parent_block = /** @type {import('#client').Block} */ (current_block); const block = create_block(); @@ -128,7 +131,7 @@ export function element(anchor, get_tag, is_svg, render_fn) { anchor.before(element); if (prev_element) { - swap_block_dom(parent_block, prev_element, element); + swap_block_dom(parent_block, parent_effect, prev_element, element); prev_element.remove(); } }, diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js index bf70cd3e98..64ac2fa296 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js @@ -10,7 +10,7 @@ import { remove } from '../reconciler.js'; import { create_block } from './utils.js'; /** - * @param {(anchor: Node | null) => void} render_fn + * @param {(anchor: Node | null) => import('#client').Dom | void} render_fn * @returns {void} */ export function head(render_fn) { @@ -29,19 +29,22 @@ export function head(render_fn) { } try { + /** @type {import('#client').Dom | null} */ + var dom = null; + const head_effect = render_effect( () => { - const current = block.d; - if (current !== null) { - remove(current); - block.d = null; + if (dom !== null) { + remove(dom); + head_effect.dom = block.d = dom = null; } let anchor = null; if (!hydrating) { anchor = empty(); document.head.appendChild(anchor); } - render_fn(anchor); + + dom = render_fn(anchor) ?? null; }, block, false diff --git a/packages/svelte/src/internal/client/dom/template.js b/packages/svelte/src/internal/client/dom/template.js index 8fcd271ecd..a0bcb61fd5 100644 --- a/packages/svelte/src/internal/client/dom/template.js +++ b/packages/svelte/src/internal/client/dom/template.js @@ -5,7 +5,7 @@ import { create_fragment_with_script_from_html, insert } from './reconciler.js'; -import { current_block } from '../runtime.js'; +import { current_block, current_effect } from '../runtime.js'; import { is_array } from '../utils.js'; /** @@ -192,6 +192,7 @@ function close_template(dom, is_fragment, anchor) { insert(current, anchor); } + /** @type {import('#client').Effect} */ (current_effect).dom = current; /** @type {import('#client').Block} */ (current_block).d = current; return current; diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index ebe1a422cb..c1788378ee 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -38,6 +38,7 @@ function create_effect(type, fn, sync, block = current_block, init = true) { /** @type {import('#client').Effect} */ const signal = { parent: current_effect, + dom: null, block, deps: null, f: type | DIRTY, diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts index c0aceff874..c7249cd7f2 100644 --- a/packages/svelte/src/internal/client/reactivity/types.d.ts +++ b/packages/svelte/src/internal/client/reactivity/types.d.ts @@ -1,4 +1,4 @@ -import type { Block, ComponentContext, Equals, TransitionManager } from '#client'; +import type { Block, ComponentContext, Dom, Equals, TransitionManager } from '#client'; import type { EFFECT, PRE_EFFECT, RENDER_EFFECT } from '../constants'; export type EffectType = typeof EFFECT | typeof PRE_EFFECT | typeof RENDER_EFFECT; @@ -37,6 +37,7 @@ export interface Derived extends Value, Reaction { export interface Effect extends Reaction { parent: Effect | null; + dom: Dom | null; /** The block associated with this effect */ block: null | Block; /** The associated component context */