chore: move DOM-related effect properties to `effect.nodes` (#17293)

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* changeset

* unused
pull/17295/head
Rich Harris 9 months ago committed by GitHub
parent 8dd8e3ec0b
commit 1f3f1826e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
chore: move DOM-related effect properties to `effect.nodes`

@ -110,13 +110,13 @@ export function log_effect_tree(effect, depth = 0) {
console.groupEnd(); console.groupEnd();
} }
if (effect.nodes_start && effect.nodes_end) { if (effect.nodes) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(effect.nodes_start); console.log(effect.nodes.start);
if (effect.nodes_start !== effect.nodes_end) { if (effect.nodes.start !== effect.nodes.end) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(effect.nodes_end); console.log(effect.nodes.end);
} }
} }

@ -1,4 +1,4 @@
/** @import { EachItem, EachState, Effect, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */ /** @import { EachItem, EachState, Effect, EffectNodes, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */
/** @import { Batch } from '../../reactivity/batch.js'; */ /** @import { Batch } from '../../reactivity/batch.js'; */
import { import {
EACH_INDEX_REACTIVE, EACH_INDEX_REACTIVE,
@ -43,18 +43,6 @@ import { DEV } from 'esm-env';
import { derived_safe_equal } from '../../reactivity/deriveds.js'; import { derived_safe_equal } from '../../reactivity/deriveds.js';
import { current_batch } from '../../reactivity/batch.js'; import { current_batch } from '../../reactivity/batch.js';
/**
* The row of a keyed each block that is currently updating. We track this
* so that `animate:` directives have something to attach themselves to
* @type {EachItem | null}
*/
export let current_each_item = null;
/** @param {EachItem | null} item */
export function set_current_each_item(item) {
current_each_item = item;
}
/** /**
* @param {any} _ * @param {any} _
* @param {number} i * @param {number} i
@ -395,7 +383,7 @@ function reconcile(state, array, anchor, flags, get_key) {
// offscreen == coming in now, no animation in that case, // offscreen == coming in now, no animation in that case,
// else this would happen https://github.com/sveltejs/svelte/issues/17181 // else this would happen https://github.com/sveltejs/svelte/issues/17181
if (item.o) { if (item.o) {
item.a?.measure(); item.e.nodes?.a?.measure();
(to_animate ??= new Set()).add(item); (to_animate ??= new Set()).add(item);
} }
} }
@ -430,7 +418,7 @@ function reconcile(state, array, anchor, flags, get_key) {
if ((item.e.f & INERT) !== 0) { if ((item.e.f & INERT) !== 0) {
resume_effect(item.e); resume_effect(item.e);
if (is_animated) { if (is_animated) {
item.a?.unfix(); item.e.nodes?.a?.unfix();
(to_animate ??= new Set()).delete(item); (to_animate ??= new Set()).delete(item);
} }
} }
@ -527,11 +515,11 @@ function reconcile(state, array, anchor, flags, get_key) {
if (is_animated) { if (is_animated) {
for (i = 0; i < destroy_length; i += 1) { for (i = 0; i < destroy_length; i += 1) {
to_destroy[i].a?.measure(); to_destroy[i].e.nodes?.a?.measure();
} }
for (i = 0; i < destroy_length; i += 1) { for (i = 0; i < destroy_length; i += 1) {
to_destroy[i].a?.fix(); to_destroy[i].e.nodes?.a?.fix();
} }
} }
@ -555,7 +543,7 @@ function reconcile(state, array, anchor, flags, get_key) {
queue_micro_task(() => { queue_micro_task(() => {
if (to_animate === undefined) return; if (to_animate === undefined) return;
for (item of to_animate) { for (item of to_animate) {
item.a?.apply(); item.e.nodes?.a?.apply();
} }
}); });
} }
@ -574,7 +562,6 @@ function reconcile(state, array, anchor, flags, get_key) {
* @returns {EachItem} * @returns {EachItem}
*/ */
function create_item(anchor, prev, value, key, index, render_fn, flags, get_collection) { function create_item(anchor, prev, value, key, index, render_fn, flags, get_collection) {
var previous_each_item = current_each_item;
var reactive = (flags & EACH_ITEM_REACTIVE) !== 0; var reactive = (flags & EACH_ITEM_REACTIVE) !== 0;
var mutable = (flags & EACH_ITEM_IMMUTABLE) === 0; var mutable = (flags & EACH_ITEM_IMMUTABLE) === 0;
@ -596,7 +583,6 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
i, i,
v, v,
k: key, k: key,
a: null,
// @ts-expect-error // @ts-expect-error
e: null, e: null,
o: false, o: false,
@ -604,27 +590,21 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
next: null next: null
}; };
current_each_item = item; if (anchor === null) {
var fragment = document.createDocumentFragment();
try { fragment.append((anchor = create_text()));
if (anchor === null) { }
var fragment = document.createDocumentFragment();
fragment.append((anchor = create_text()));
}
item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection));
if (prev !== null) { item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection));
// we only need to set `prev.next = item`, because
// `item.prev = prev` was set on initialization.
// the effects themselves are already linked
prev.next = item;
}
return item; if (prev !== null) {
} finally { // we only need to set `prev.next = item`, because
current_each_item = previous_each_item; // `item.prev = prev` was set on initialization.
// the effects themselves are already linked
prev.next = item;
} }
return item;
} }
/** /**
@ -633,10 +613,12 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
* @param {Text | Element | Comment} anchor * @param {Text | Element | Comment} anchor
*/ */
function move(item, next, anchor) { function move(item, next, anchor) {
var end = item.next ? /** @type {TemplateNode} */ (item.next.e.nodes_start) : anchor; if (!item.e.nodes) return;
var end = item.next ? /** @type {EffectNodes} */ (item.next.e.nodes).start : anchor;
var dest = next ? /** @type {TemplateNode} */ (next.e.nodes_start) : anchor; var dest = next ? /** @type {EffectNodes} */ (next.e.nodes).start : anchor;
var node = /** @type {TemplateNode} */ (item.e.nodes_start); var node = /** @type {TemplateNode} */ (item.e.nodes.start);
while (node !== null && node !== end) { while (node !== null && node !== end) {
var next_node = /** @type {TemplateNode} */ (get_next_sibling(node)); var next_node = /** @type {TemplateNode} */ (get_next_sibling(node));

@ -54,9 +54,9 @@ export function html(node, get_value, svg = false, mathml = false, skip_warning
return; return;
} }
if (effect.nodes_start !== null) { if (effect.nodes !== null) {
remove_effect_dom(effect.nodes_start, /** @type {TemplateNode} */ (effect.nodes_end)); remove_effect_dom(effect.nodes.start, /** @type {TemplateNode} */ (effect.nodes.end));
effect.nodes_start = effect.nodes_end = null; effect.nodes = null;
} }
if (value === '') return; if (value === '') return;

@ -1,4 +1,4 @@
/** @import { Effect, TemplateNode } from '#client' */ /** @import { Effect, EffectNodes, TemplateNode } from '#client' */
import { FILENAME, NAMESPACE_SVG } from '../../../../constants.js'; import { FILENAME, NAMESPACE_SVG } from '../../../../constants.js';
import { import {
hydrate_next, hydrate_next,
@ -10,7 +10,6 @@ import {
import { create_text, get_first_child } from '../operations.js'; import { create_text, get_first_child } from '../operations.js';
import { block, teardown } from '../../reactivity/effects.js'; import { block, teardown } from '../../reactivity/effects.js';
import { set_should_intro } from '../../render.js'; import { set_should_intro } from '../../render.js';
import { current_each_item, set_current_each_item } from './each.js';
import { active_effect } from '../../runtime.js'; import { active_effect } from '../../runtime.js';
import { component_context, dev_stack } from '../../context.js'; import { component_context, dev_stack } from '../../context.js';
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
@ -18,6 +17,7 @@ import { EFFECT_TRANSPARENT, ELEMENT_NODE } from '#client/constants';
import { assign_nodes } from '../template.js'; import { assign_nodes } from '../template.js';
import { is_raw_text_element } from '../../../../utils.js'; import { is_raw_text_element } from '../../../../utils.js';
import { BranchManager } from './branches.js'; import { BranchManager } from './branches.js';
import { set_animation_effect_override } from '../elements/transitions.js';
/** /**
* @param {Comment | Element} node * @param {Comment | Element} node
@ -48,11 +48,10 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
var anchor = /** @type {TemplateNode} */ (hydrating ? hydrate_node : node); var anchor = /** @type {TemplateNode} */ (hydrating ? hydrate_node : node);
/** /**
* The keyed `{#each ...}` item block, if any, that this element is inside.
* We track this so we can set it when changing the element, allowing any * We track this so we can set it when changing the element, allowing any
* `animate:` directive to bind itself to the correct block * `animate:` directive to bind itself to the correct block
*/ */
var each_item_block = current_each_item; var parent_effect = /** @type {Effect} */ (active_effect);
var branches = new BranchManager(anchor, false); var branches = new BranchManager(anchor, false);
@ -67,10 +66,6 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
} }
branches.ensure(next_tag, (anchor) => { branches.ensure(next_tag, (anchor) => {
// See explanation of `each_item_block` above
var previous_each_item = current_each_item;
set_current_each_item(each_item_block);
if (next_tag) { if (next_tag) {
element = hydrating element = hydrating
? /** @type {Element} */ (element) ? /** @type {Element} */ (element)
@ -112,21 +107,23 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
} }
} }
set_animation_effect_override(parent_effect);
// `child_anchor` is undefined if this is a void element, but we still // `child_anchor` is undefined if this is a void element, but we still
// need to call `render_fn` in order to run actions etc. If the element // need to call `render_fn` in order to run actions etc. If the element
// contains children, it's a user error (which is warned on elsewhere) // contains children, it's a user error (which is warned on elsewhere)
// and the DOM will be silently discarded // and the DOM will be silently discarded
render_fn(element, child_anchor); render_fn(element, child_anchor);
set_animation_effect_override(null);
} }
// we do this after calling `render_fn` so that child effects don't override `nodes.end` // we do this after calling `render_fn` so that child effects don't override `nodes.end`
/** @type {Effect} */ (active_effect).nodes_end = element; /** @type {Effect & { nodes: EffectNodes }} */ (active_effect).nodes.end = element;
anchor.before(element); anchor.before(element);
} }
set_current_each_item(previous_each_item);
if (hydrating) { if (hydrating) {
set_hydrate_node(anchor); set_hydrate_node(anchor);
} }

@ -1,10 +1,9 @@
/** @import { AnimateFn, Animation, AnimationConfig, EachItem, Effect, TransitionFn, TransitionManager } from '#client' */ /** @import { AnimateFn, Animation, AnimationConfig, EachItem, Effect, EffectNodes, TransitionFn, TransitionManager } from '#client' */
import { noop, is_function } from '../../../shared/utils.js'; import { noop, is_function } from '../../../shared/utils.js';
import { effect } from '../../reactivity/effects.js'; import { effect } from '../../reactivity/effects.js';
import { active_effect, untrack } from '../../runtime.js'; import { active_effect, untrack } from '../../runtime.js';
import { loop } from '../../loop.js'; import { loop } from '../../loop.js';
import { should_intro } from '../../render.js'; import { should_intro } from '../../render.js';
import { current_each_item } from '../blocks/each.js';
import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../constants.js'; import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../constants.js';
import { BLOCK_EFFECT, EFFECT_RAN, EFFECT_TRANSPARENT } from '#client/constants'; import { BLOCK_EFFECT, EFFECT_RAN, EFFECT_TRANSPARENT } from '#client/constants';
import { queue_micro_task } from '../task.js'; import { queue_micro_task } from '../task.js';
@ -66,6 +65,14 @@ function css_to_keyframe(css) {
/** @param {number} t */ /** @param {number} t */
const linear = (t) => t; const linear = (t) => t;
/** @type {Effect | null} */
let animation_effect_override = null;
/** @param {Effect | null} v */
export function set_animation_effect_override(v) {
animation_effect_override = v;
}
/** /**
* Called inside keyed `{#each ...}` blocks (as `$.animation(...)`). This creates an animation manager * Called inside keyed `{#each ...}` blocks (as `$.animation(...)`). This creates an animation manager
* and attaches it to the block, so that moves can be animated following reconciliation. * and attaches it to the block, so that moves can be animated following reconciliation.
@ -75,7 +82,8 @@ const linear = (t) => t;
* @param {(() => P) | null} get_params * @param {(() => P) | null} get_params
*/ */
export function animation(element, get_fn, get_params) { export function animation(element, get_fn, get_params) {
var item = /** @type {EachItem} */ (current_each_item); var effect = animation_effect_override ?? /** @type {Effect} */ (active_effect);
var nodes = /** @type {EffectNodes} */ (effect.nodes);
/** @type {DOMRect} */ /** @type {DOMRect} */
var from; var from;
@ -89,7 +97,7 @@ export function animation(element, get_fn, get_params) {
/** @type {null | { position: string, width: string, height: string, transform: string }} */ /** @type {null | { position: string, width: string, height: string, transform: string }} */
var original_styles = null; var original_styles = null;
item.a ??= { nodes.a ??= {
element, element,
measure() { measure() {
from = this.element.getBoundingClientRect(); from = this.element.getBoundingClientRect();
@ -161,7 +169,7 @@ export function animation(element, get_fn, get_params) {
// when an animation manager already exists, if the tag changes. in that case, we need to // when an animation manager already exists, if the tag changes. in that case, we need to
// swap out the element rather than creating a new manager, in case it happened at the same // swap out the element rather than creating a new manager, in case it happened at the same
// moment as a reconciliation // moment as a reconciliation
item.a.element = element; nodes.a.element = element;
} }
/** /**
@ -265,9 +273,9 @@ export function transition(flags, element, get_fn, get_params) {
} }
}; };
var e = /** @type {Effect} */ (active_effect); var e = /** @type {Effect & { nodes: EffectNodes }} */ (active_effect);
(e.transitions ??= []).push(transition); (e.nodes.t ??= []).push(transition);
// if this is a local transition, we only want to run it if the parent (branch) effect's // if this is a local transition, we only want to run it if the parent (branch) effect's
// parent (block) effect is where the state change happened. we can determine that by // parent (block) effect is where the state change happened. we can determine that by

@ -1,4 +1,4 @@
/** @import { Effect, TemplateNode } from '#client' */ /** @import { Effect, EffectNodes, TemplateNode } from '#client' */
/** @import { TemplateStructure } from './types' */ /** @import { TemplateStructure } from './types' */
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from './hydration.js'; import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
import { import {
@ -28,9 +28,8 @@ import { COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, EFFECT_RAN, TEXT_NODE } from '#cl
*/ */
export function assign_nodes(start, end) { export function assign_nodes(start, end) {
var effect = /** @type {Effect} */ (active_effect); var effect = /** @type {Effect} */ (active_effect);
if (effect.nodes_start === null) { if (effect.nodes === null) {
effect.nodes_start = start; effect.nodes = { start, end, a: null, t: null };
effect.nodes_end = end;
} }
} }
@ -270,7 +269,8 @@ function run_scripts(node) {
/** @type {HTMLElement} */ (node).tagName === 'SCRIPT' /** @type {HTMLElement} */ (node).tagName === 'SCRIPT'
? [/** @type {HTMLScriptElement} */ (node)] ? [/** @type {HTMLScriptElement} */ (node)]
: node.querySelectorAll('script'); : node.querySelectorAll('script');
const effect = /** @type {Effect} */ (active_effect);
const effect = /** @type {Effect & { nodes: EffectNodes }} */ (active_effect);
for (const script of scripts) { for (const script of scripts) {
const clone = document.createElement('script'); const clone = document.createElement('script');
@ -282,10 +282,10 @@ function run_scripts(node) {
// The script has changed - if it's at the edges, the effect now points at dead nodes // The script has changed - if it's at the edges, the effect now points at dead nodes
if (is_fragment ? node.firstChild === script : node === script) { if (is_fragment ? node.firstChild === script : node === script) {
effect.nodes_start = clone; effect.nodes.start = clone;
} }
if (is_fragment ? node.lastChild === script : node === script) { if (is_fragment ? node.lastChild === script : node === script) {
effect.nodes_end = clone; effect.nodes.end = clone;
} }
script.replaceWith(clone); script.replaceWith(clone);
@ -344,13 +344,15 @@ export function comment() {
*/ */
export function append(anchor, dom) { export function append(anchor, dom) {
if (hydrating) { if (hydrating) {
var effect = /** @type {Effect} */ (active_effect); var effect = /** @type {Effect & { nodes: EffectNodes }} */ (active_effect);
// When hydrating and outer component and an inner component is async, i.e. blocked on a promise, // When hydrating and outer component and an inner component is async, i.e. blocked on a promise,
// then by the time the inner resolves we have already advanced to the end of the hydrated nodes // then by the time the inner resolves we have already advanced to the end of the hydrated nodes
// of the parent component. Check for defined for that reason to avoid rewinding the parent's end marker. // of the parent component. Check for defined for that reason to avoid rewinding the parent's end marker.
if ((effect.f & EFFECT_RAN) === 0 || effect.nodes_end === null) { if ((effect.f & EFFECT_RAN) === 0 || effect.nodes.end === null) {
effect.nodes_end = hydrate_node; effect.nodes.end = hydrate_node;
} }
hydrate_next(); hydrate_next();
return; return;
} }

@ -26,7 +26,6 @@ import {
} from './deriveds.js'; } from './deriveds.js';
import { aborted } from './effects.js'; import { aborted } from './effects.js';
import { hydrate_next, hydrating, set_hydrate_node, skip_nodes } from '../dom/hydration.js'; import { hydrate_next, hydrating, set_hydrate_node, skip_nodes } from '../dom/hydration.js';
import { current_each_item, set_current_each_item } from '../dom/blocks/each.js';
/** /**
* @param {Array<Promise<void>>} blockers * @param {Array<Promise<void>>} blockers
@ -90,11 +89,7 @@ export function flatten(blockers, sync, async, fn) {
* @param {(values: Value[]) => any} fn * @param {(values: Value[]) => any} fn
*/ */
export function run_after_blockers(blockers, fn) { export function run_after_blockers(blockers, fn) {
var each_item = current_each_item; // TODO should this be part of capture? flatten(blockers, [], [], fn);
flatten(blockers, [], [], (v) => {
set_current_each_item(each_item);
fn(v);
});
} }
/** /**

@ -708,7 +708,7 @@ function flush_queued_effects(effects) {
// don't know if we need to keep them until they are executed. Doing the check // don't know if we need to keep them until they are executed. Doing the check
// here (rather than in `update_effect`) allows us to skip the work for // here (rather than in `update_effect`) allows us to skip the work for
// immediate effects. // immediate effects.
if (effect.deps === null && effect.first === null && effect.nodes_start === null) { if (effect.deps === null && effect.first === null && effect.nodes === null) {
// if there's no teardown or abort controller we completely unlink // if there's no teardown or abort controller we completely unlink
// the effect from the graph // the effect from the graph
if (effect.teardown === null && effect.ac === null) { if (effect.teardown === null && effect.ac === null) {

@ -101,8 +101,7 @@ function create_effect(type, fn, sync) {
var effect = { var effect = {
ctx: component_context, ctx: component_context,
deps: null, deps: null,
nodes_start: null, nodes: null,
nodes_end: null,
f: type | DIRTY | CONNECTED, f: type | DIRTY | CONNECTED,
first: null, first: null,
fn, fn,
@ -112,7 +111,6 @@ function create_effect(type, fn, sync) {
b: parent && parent.b, b: parent && parent.b,
prev: null, prev: null,
teardown: null, teardown: null,
transitions: null,
wv: 0, wv: 0,
ac: null ac: null
}; };
@ -143,7 +141,7 @@ function create_effect(type, fn, sync) {
sync && sync &&
e.deps === null && e.deps === null &&
e.teardown === null && e.teardown === null &&
e.nodes_start === null && e.nodes === null &&
e.first === e.last && // either `null`, or a singular child e.first === e.last && // either `null`, or a singular child
(e.f & EFFECT_PRESERVED) === 0 (e.f & EFFECT_PRESERVED) === 0
) { ) {
@ -497,10 +495,10 @@ export function destroy_effect(effect, remove_dom = true) {
if ( if (
(remove_dom || (effect.f & HEAD_EFFECT) !== 0) && (remove_dom || (effect.f & HEAD_EFFECT) !== 0) &&
effect.nodes_start !== null && effect.nodes !== null &&
effect.nodes_end !== null effect.nodes.end !== null
) { ) {
remove_effect_dom(effect.nodes_start, /** @type {TemplateNode} */ (effect.nodes_end)); remove_effect_dom(effect.nodes.start, /** @type {TemplateNode} */ (effect.nodes.end));
removed = true; removed = true;
} }
@ -508,7 +506,7 @@ export function destroy_effect(effect, remove_dom = true) {
remove_reactions(effect, 0); remove_reactions(effect, 0);
set_signal_status(effect, DESTROYED); set_signal_status(effect, DESTROYED);
var transitions = effect.transitions; var transitions = effect.nodes && effect.nodes.t;
if (transitions !== null) { if (transitions !== null) {
for (const transition of transitions) { for (const transition of transitions) {
@ -537,8 +535,7 @@ export function destroy_effect(effect, remove_dom = true) {
effect.ctx = effect.ctx =
effect.deps = effect.deps =
effect.fn = effect.fn =
effect.nodes_start = effect.nodes =
effect.nodes_end =
effect.ac = effect.ac =
null; null;
} }
@ -624,8 +621,10 @@ export function pause_children(effect, transitions, local) {
if ((effect.f & INERT) !== 0) return; if ((effect.f & INERT) !== 0) return;
effect.f ^= INERT; effect.f ^= INERT;
if (effect.transitions !== null) { var t = effect.nodes && effect.nodes.t;
for (const transition of effect.transitions) {
if (t !== null) {
for (const transition of t) {
if (transition.is_global || local) { if (transition.is_global || local) {
transitions.push(transition); transitions.push(transition);
} }
@ -688,8 +687,10 @@ function resume_children(effect, local) {
child = sibling; child = sibling;
} }
if (effect.transitions !== null) { var t = effect.nodes && effect.nodes.t;
for (const transition of effect.transitions) {
if (t !== null) {
for (const transition of t) {
if (transition.is_global || local) { if (transition.is_global || local) {
transition.in(); transition.in();
} }
@ -706,8 +707,11 @@ export function aborted(effect = /** @type {Effect} */ (active_effect)) {
* @param {DocumentFragment} fragment * @param {DocumentFragment} fragment
*/ */
export function move_effect(effect, fragment) { export function move_effect(effect, fragment) {
var node = effect.nodes_start; if (!effect.nodes) return;
var end = effect.nodes_end;
/** @type {TemplateNode | null} */
var node = effect.nodes.start;
var end = effect.nodes.end;
while (node !== null) { while (node !== null) {
/** @type {TemplateNode | null} */ /** @type {TemplateNode | null} */

@ -1,4 +1,5 @@
import type { import type {
AnimationManager,
ComponentContext, ComponentContext,
DevStackEntry, DevStackEntry,
Equals, Equals,
@ -60,6 +61,15 @@ export interface Derived<V = unknown> extends Value<V>, Reaction {
parent: Effect | Derived | null; parent: Effect | Derived | null;
} }
export interface EffectNodes {
start: TemplateNode;
end: TemplateNode | null;
/** $.animation */
a: AnimationManager | null;
/** $.transition */
t: TransitionManager[] | null;
}
export interface Effect extends Reaction { export interface Effect extends Reaction {
/** /**
* Branch effects store their start/end nodes so that they can be * Branch effects store their start/end nodes so that they can be
@ -67,14 +77,11 @@ export interface Effect extends Reaction {
* block is reconciled. In the case of a single text/element node, * block is reconciled. In the case of a single text/element node,
* `start` and `end` will be the same. * `start` and `end` will be the same.
*/ */
nodes_start: null | TemplateNode; nodes: null | EffectNodes;
nodes_end: null | TemplateNode;
/** The effect function */ /** The effect function */
fn: null | (() => void | (() => void)); fn: null | (() => void | (() => void));
/** The teardown function returned from the effect function */ /** The teardown function returned from the effect function */
teardown: null | (() => void); teardown: null | (() => void);
/** Transition managers created with `$.transition` */
transitions: null | TransitionManager[];
/** Next sibling child effect created inside the parent signal */ /** Next sibling child effect created inside the parent signal */
prev: null | Effect; prev: null | Effect;
/** Next sibling child effect created inside the parent signal */ /** Next sibling child effect created inside the parent signal */

@ -1,4 +1,4 @@
/** @import { ComponentContext, Effect, TemplateNode } from '#client' */ /** @import { ComponentContext, Effect, EffectNodes, TemplateNode } from '#client' */
/** @import { Component, ComponentType, SvelteComponent, MountOptions } from '../../index.js' */ /** @import { Component, ComponentType, SvelteComponent, MountOptions } from '../../index.js' */
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
import { import {
@ -228,7 +228,7 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro
should_intro = true; should_intro = true;
if (hydrating) { if (hydrating) {
/** @type {Effect} */ (active_effect).nodes_end = hydrate_node; /** @type {Effect & { nodes: EffectNodes }} */ (active_effect).nodes.end = hydrate_node;
if ( if (
hydrate_node === null || hydrate_node === null ||

@ -84,8 +84,6 @@ export type EachState = {
}; };
export type EachItem = { export type EachItem = {
/** animation manager */
a: AnimationManager | null;
/** effect */ /** effect */
e: Effect; e: Effect;
/** item */ /** item */

Loading…
Cancel
Save