chore: tidy up some hydration code (#10944)

* tidy up

* tidy up
pull/10934/head
Rich Harris 1 year ago committed by GitHub
parent f8fcbf0b0b
commit c683484f5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -43,8 +43,8 @@ export function set_current_each_item(item) {
* @param {number} flags * @param {number} flags
* @param {() => V[]} get_collection * @param {() => V[]} get_collection
* @param {null | ((item: V) => string)} get_key * @param {null | ((item: V) => string)} get_key
* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn * @param {(anchor: Node, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn * @param {null | ((anchor: Node) => void)} fallback_fn
* @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn * @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn
* @returns {void} * @returns {void}
*/ */
@ -126,7 +126,7 @@ function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn, re
} }
child_anchor = hydrate_anchor(child_anchor); child_anchor = hydrate_anchor(child_anchor);
b_items[i] = create_item(array[i], keys?.[i], i, render_fn, flags); b_items[i] = create_item(child_anchor, array[i], keys?.[i], i, render_fn, flags);
child_anchor = /** @type {Comment} */ (child_anchor.nextSibling); child_anchor = /** @type {Comment} */ (child_anchor.nextSibling);
} }
@ -153,7 +153,7 @@ function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn, re
resume_effect(fallback); resume_effect(fallback);
} else { } else {
fallback = render_effect(() => { fallback = render_effect(() => {
var dom = fallback_fn(hydrating ? null : anchor); var dom = fallback_fn(anchor);
return () => { return () => {
if (dom !== undefined) { if (dom !== undefined) {
@ -193,8 +193,8 @@ function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn, re
* @param {number} flags * @param {number} flags
* @param {() => V[]} get_collection * @param {() => V[]} get_collection
* @param {null | ((item: V) => string)} get_key * @param {null | ((item: V) => string)} get_key
* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn * @param {(anchor: Node, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node | null) => void)} [fallback_fn] * @param {null | ((anchor: Node) => void)} [fallback_fn]
* @returns {void} * @returns {void}
*/ */
export function each_keyed(anchor, flags, get_collection, get_key, render_fn, fallback_fn = null) { export function each_keyed(anchor, flags, get_collection, get_key, render_fn, fallback_fn = null) {
@ -206,8 +206,8 @@ export function each_keyed(anchor, flags, get_collection, get_key, render_fn, fa
* @param {Element | Comment} anchor * @param {Element | Comment} anchor
* @param {number} flags * @param {number} flags
* @param {() => V[]} get_collection * @param {() => V[]} get_collection
* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn * @param {(anchor: Node, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node | null) => void)} [fallback_fn] * @param {null | ((anchor: Node) => void)} [fallback_fn]
* @returns {void} * @returns {void}
*/ */
export function each_indexed(anchor, flags, get_collection, render_fn, fallback_fn = null) { export function each_indexed(anchor, flags, get_collection, render_fn, fallback_fn = null) {
@ -219,7 +219,7 @@ export function each_indexed(anchor, flags, get_collection, render_fn, fallback_
* @param {Array<V>} array * @param {Array<V>} array
* @param {import('#client').EachState} state * @param {import('#client').EachState} state
* @param {Element | Comment | Text} anchor * @param {Element | Comment | Text} anchor
* @param {(anchor: null, item: V, index: number | import('#client').Source<number>) => void} render_fn * @param {(anchor: Node, item: V, index: number | import('#client').Source<number>) => void} render_fn
* @param {number} flags * @param {number} flags
* @returns {void} * @returns {void}
*/ */
@ -249,9 +249,8 @@ function reconcile_indexed_array(array, state, anchor, render_fn, flags) {
// add items // add items
for (; i < b; i += 1) { for (; i < b; i += 1) {
value = array[i]; value = array[i];
item = create_item(value, null, i, render_fn, flags); item = create_item(anchor, value, null, i, render_fn, flags);
b_items[i] = item; b_items[i] = item;
insert_item(item, anchor);
} }
state.items = b_items; state.items = b_items;
@ -276,7 +275,7 @@ function reconcile_indexed_array(array, state, anchor, render_fn, flags) {
* @param {Array<V>} array * @param {Array<V>} array
* @param {import('#client').EachState} state * @param {import('#client').EachState} state
* @param {Element | Comment | Text} anchor * @param {Element | Comment | Text} anchor
* @param {(anchor: null, item: V, index: number | import('#client').Source<number>) => void} render_fn * @param {(anchor: Node, item: V, index: number | import('#client').Source<number>) => void} render_fn
* @param {number} flags * @param {number} flags
* @param {any[]} keys * @param {any[]} keys
* @returns {void} * @returns {void}
@ -327,9 +326,8 @@ function reconcile_tracked_array(array, state, anchor, render_fn, flags, keys) {
if (start === a) { if (start === a) {
// add only // add only
while (start < b) { while (start < b) {
item = create_item(array[start], keys[start], start, render_fn, flags); item = create_item(anchor, array[start], keys[start], start, render_fn, flags);
b_items[start++] = item; b_items[start++] = item;
insert_item(item, anchor);
} }
} else if (start === b) { } else if (start === b) {
// remove only // remove only
@ -398,20 +396,21 @@ function reconcile_tracked_array(array, state, anchor, render_fn, flags, keys) {
// working from the back, insert new or moved items // working from the back, insert new or moved items
while (b-- > start) { while (b-- > start) {
index = sources[b - start]; index = sources[b - start];
var insert = index === NEW_ITEM; var should_insert = index === NEW_ITEM;
if (insert) { if (should_insert) {
item = create_item(array[b], keys[b], b, render_fn, flags); if (last_item !== undefined) anchor = get_first_child(last_item);
item = create_item(anchor, array[b], keys[b], b, render_fn, flags);
} else { } else {
item = b_items[b]; item = b_items[b];
if (should_update) { if (should_update) {
update_item(item, array[b], b, flags); update_item(item, array[b], b, flags);
} }
}
if (insert || (moved && index !== LIS_ITEM)) { if (moved && index !== LIS_ITEM) {
last_sibling = last_item === undefined ? anchor : get_first_child(last_item); if (last_item !== undefined) anchor = get_first_child(last_item);
anchor = insert_item(item, last_sibling); insert(/** @type {import('#client').Dom} */ (item.e.dom), anchor);
}
} }
last_item = b_items[b] = item; last_item = b_items[b] = item;
@ -510,16 +509,6 @@ function mark_lis(a) {
} }
} }
/**
* @param {import('#client').EachItem} item
* @param {Text | Element | Comment} anchor
* @returns {Text | Element | Comment}
*/
function insert_item(item, anchor) {
var current = /** @type {import('#client').Dom} */ (item.e.dom);
return insert(current, anchor);
}
/** /**
* @param {import('#client').EachItem} item * @param {import('#client').EachItem} item
* @returns {Text | Element | Comment} * @returns {Text | Element | Comment}
@ -555,14 +544,15 @@ function update_item(item, value, index, type) {
/** /**
* @template V * @template V
* @param {Node} anchor
* @param {V} value * @param {V} value
* @param {unknown} key * @param {unknown} key
* @param {number} index * @param {number} index
* @param {(anchor: null, item: V, index: number | import('#client').Value<number>) => void} render_fn * @param {(anchor: Node, item: V, index: number | import('#client').Value<number>) => void} render_fn
* @param {number} flags * @param {number} flags
* @returns {import('#client').EachItem} * @returns {import('#client').EachItem}
*/ */
function create_item(value, key, index, render_fn, flags) { function create_item(anchor, value, key, index, render_fn, flags) {
var each_item_not_reactive = (flags & EACH_ITEM_REACTIVE) === 0; var each_item_not_reactive = (flags & EACH_ITEM_REACTIVE) === 0;
/** @type {import('#client').EachItem} */ /** @type {import('#client').EachItem} */
@ -589,7 +579,7 @@ function create_item(value, key, index, render_fn, flags) {
current_each_item = item; current_each_item = item;
item.e = render_effect(() => { item.e = render_effect(() => {
var dom = render_fn(null, item.v, item.i); var dom = render_fn(anchor, item.v, item.i);
return () => { return () => {
if (dom !== undefined) { if (dom !== undefined) {

@ -4,7 +4,7 @@ import { render_effect } from '../../reactivity/effects.js';
import { remove } from '../reconciler.js'; import { remove } from '../reconciler.js';
/** /**
* @param {(anchor: Node | null) => import('#client').Dom | void} render_fn * @param {(anchor: Node) => import('#client').Dom | void} render_fn
* @returns {void} * @returns {void}
*/ */
export function head(render_fn) { export function head(render_fn) {
@ -36,7 +36,7 @@ export function head(render_fn) {
head_effect.dom = dom = null; head_effect.dom = dom = null;
} }
dom = render_fn(hydrating ? null : anchor) ?? null; dom = render_fn(anchor) ?? null;
}); });
head_effect.ondestroy = () => { head_effect.ondestroy = () => {
@ -46,7 +46,7 @@ export function head(render_fn) {
}; };
} finally { } finally {
if (was_hydrating) { if (was_hydrating) {
set_hydrate_nodes(previous_hydrate_nodes); set_hydrate_nodes(/** @type {import('#client').TemplateNode[]} */ (previous_hydrate_nodes));
} }
} }
} }

@ -17,12 +17,9 @@ export function set_hydrating(value) {
*/ */
export let hydrate_nodes = /** @type {any} */ (null); export let hydrate_nodes = /** @type {any} */ (null);
/** /** @param {import('#client').TemplateNode[]} nodes */
* @param {null | import('#client').TemplateNode[]} nodes
* @returns {void}
*/
export function set_hydrate_nodes(nodes) { export function set_hydrate_nodes(nodes) {
hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes); hydrate_nodes = nodes;
} }
/** /**

@ -30,7 +30,6 @@ export function create_fragment_with_script_from_html(html) {
/** /**
* @param {import('#client').Dom} current * @param {import('#client').Dom} current
* @param {Text | Element | Comment} sibling * @param {Text | Element | Comment} sibling
* @returns {Text | Element | Comment}
*/ */
export function insert(current, sibling) { export function insert(current, sibling) {
if (!current) return sibling; if (!current) return sibling;
@ -39,12 +38,9 @@ export function insert(current, sibling) {
for (var i = 0; i < current.length; i++) { for (var i = 0; i < current.length; i++) {
sibling.before(/** @type {Node} */ (current[i])); sibling.before(/** @type {Node} */ (current[i]));
} }
} else {
return current[0]; sibling.before(/** @type {Node} */ (current));
} }
sibling.before(/** @type {Node} */ (current));
return /** @type {Text | Element | Comment} */ (current);
} }
/** /**

@ -145,7 +145,7 @@ export function comment() {
* and insert the elements into the dom (in client mode). * and insert the elements into the dom (in client mode).
* @param {import('#client').Dom} dom * @param {import('#client').Dom} dom
* @param {boolean} is_fragment * @param {boolean} is_fragment
* @param {null | Text | Comment | Element} anchor * @param {Text | Comment | Element} anchor
* @returns {import('#client').Dom} * @returns {import('#client').Dom}
*/ */
function close_template(dom, is_fragment, anchor) { function close_template(dom, is_fragment, anchor) {
@ -158,10 +158,8 @@ function close_template(dom, is_fragment, anchor) {
current = /** @type {import('#client').Dom} */ ([.../** @type {Node} */ (dom).childNodes]); current = /** @type {import('#client').Dom} */ ([.../** @type {Node} */ (dom).childNodes]);
} }
if (anchor !== null) { // TODO ideally we'd do `anchor.before(dom)`, but that fails because `dom` can be an array of nodes in the SVG case
// TODO as with `open_template — why is this sometimes null and sometimes not? insert(current, anchor);
insert(current, anchor);
}
} }
/** @type {import('#client').Effect} */ (current_effect).dom = current; /** @type {import('#client').Effect} */ (current_effect).dom = current;
@ -170,7 +168,7 @@ function close_template(dom, is_fragment, anchor) {
} }
/** /**
* @param {null | Text | Comment | Element} anchor * @param {Text | Comment | Element} anchor
* @param {Element | Text} dom * @param {Element | Text} dom
*/ */
export function close(anchor, dom) { export function close(anchor, dom) {
@ -178,7 +176,7 @@ export function close(anchor, dom) {
} }
/** /**
* @param {null | Text | Comment | Element} anchor * @param {Text | Comment | Element} anchor
* @param {Element | Text} dom * @param {Element | Text} dom
*/ */
export function close_frag(anchor, dom) { export function close_frag(anchor, dom) {

@ -184,7 +184,7 @@ export function hydrate(component, options) {
* @param {import('../../main/public.js').ComponentType<import('../../main/public.js').SvelteComponent<Props, Events>>} Component * @param {import('../../main/public.js').ComponentType<import('../../main/public.js').SvelteComponent<Props, Events>>} Component
* @param {{ * @param {{
* target: Document | Element | ShadowRoot; * target: Document | Element | ShadowRoot;
* anchor: null | Node; * anchor: Node;
* props?: Props; * props?: Props;
* events?: { [Property in keyof Events]: (e: Events[Property]) => any }; * events?: { [Property in keyof Events]: (e: Events[Property]) => any };
* context?: Map<any, any>; * context?: Map<any, any>;

Loading…
Cancel
Save