chore: more hydration stuff (#10896)

* this condition is always true

* rename child_frag to first_child

* no need to use is_array, it is always an array when hydrating

* simplify close_template

* spread is faster than Array.from

* avoid reassigning argument
pull/10903/head
Rich Harris 8 months ago committed by GitHub
parent 9b7331c04c
commit 32b1824198
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1202,7 +1202,7 @@ function create_block(parent, name, nodes, context) {
} else {
/** @type {(is_text: boolean) => import('estree').Expression} */
const expression = (is_text) =>
is_text ? b.call('$.child_frag', id, b.true) : b.call('$.child_frag', id);
is_text ? b.call('$.first_child', id, b.true) : b.call('$.first_child', id);
process_children(trimmed, expression, false, { ...context, state });

@ -134,18 +134,19 @@ export function child(node) {
}
/**
* @template {Node | Node[]} N
* @param {N} node
* @param {DocumentFragment | import('#client').TemplateNode[]} fragment
* @param {boolean} is_text
* @returns {Node | null}
*/
/*#__NO_SIDE_EFFECTS__*/
export function child_frag(node, is_text) {
export function first_child(fragment, is_text) {
if (!hydrating) {
return first_child_get.call(/** @type {Node} */ (node));
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
return first_child_get.call(/** @type {DocumentFragment} */ (fragment));
}
const first_node = /** @type {import('#client').TemplateNode[]} */ (node)[0];
// when we _are_ hydrating, `fragment` is an array of nodes
const first_node = /** @type {import('#client').TemplateNode[]} */ (fragment)[0];
// if an {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one

@ -93,7 +93,7 @@ export function reconcile_html(target, value, svg) {
content = /** @type {DocumentFragment} */ (/** @type {unknown} */ (content.firstChild));
}
var clone = content.cloneNode(true);
frag_nodes = Array.from(clone.childNodes);
frag_nodes = [...clone.childNodes];
frag_nodes.forEach((node) => {
target.before(node);
});

@ -87,18 +87,17 @@ export function svg_template_with_script(svg, return_fragment) {
* @param {() => Node} [template_element_fn]
* @returns {Element | DocumentFragment | Node[]}
*/
/*#__NO_SIDE_EFFECTS__*/
function open_template(is_fragment, use_clone_node, anchor, template_element_fn) {
if (hydrating) {
if (anchor !== null) {
// TODO why is this sometimes null and sometimes not? needs clear documentation
hydrate_block_anchor(anchor);
}
// In ssr+hydration optimization mode, we might remove the template_element,
// so we need to is_fragment flag to properly handle hydrated content accordingly.
const nodes = hydrate_nodes;
if (nodes !== null) {
return is_fragment ? nodes : /** @type {Element} */ (nodes[0]);
}
return is_fragment ? hydrate_nodes : /** @type {Element} */ (hydrate_nodes[0]);
}
return use_clone_node
? clone_node(/** @type {() => Element} */ (template_element_fn)(), true)
: document.importNode(/** @type {() => Element} */ (template_element_fn)(), true);
@ -108,11 +107,10 @@ function open_template(is_fragment, use_clone_node, anchor, template_element_fn)
* @param {null | Text | Comment | Element} anchor
* @param {() => Node} template_element_fn
* @param {boolean} [use_clone_node]
* @returns {Element | DocumentFragment | Node[]}
* @returns {Element}
*/
/*#__NO_SIDE_EFFECTS__*/
export function open(anchor, template_element_fn, use_clone_node = true) {
return open_template(false, use_clone_node, anchor, template_element_fn);
return /** @type {Element} */ (open_template(false, use_clone_node, anchor, template_element_fn));
}
/**
@ -121,7 +119,6 @@ export function open(anchor, template_element_fn, use_clone_node = true) {
* @param {boolean} [use_clone_node]
* @returns {Element | DocumentFragment | Node[]}
*/
/*#__NO_SIDE_EFFECTS__*/
export function open_frag(anchor, template_element_fn, use_clone_node = true) {
return open_template(true, use_clone_node, anchor, template_element_fn);
}
@ -175,21 +172,25 @@ export function comment(anchor) {
/**
* Assign the created (or in hydration mode, traversed) dom elements to the current block
* and insert the elements into the dom (in client mode).
* @param {Element | Text} dom
* @param {import('#client').Dom} dom
* @param {boolean} is_fragment
* @param {null | Text | Comment | Element} anchor
* @returns {import('#client').Dom}
*/
function close_template(dom, is_fragment, anchor) {
/** @type {import('#client').Dom} */
var current = is_fragment
? is_array(dom)
? dom
: /** @type {import('#client').TemplateNode[]} */ (Array.from(dom.childNodes))
: dom;
if (!hydrating && anchor !== null) {
insert(current, anchor);
var current = dom;
if (!hydrating) {
if (is_fragment) {
// if hydrating, `dom` is already an array of nodes, but if not then
// we need to create an array to store it on the current effect
current = /** @type {import('#client').Dom} */ ([.../** @type {Node} */ (dom).childNodes]);
}
if (anchor !== null) {
// TODO as with `open_template — why is this sometimes null and sometimes not?
insert(current, anchor);
}
}
/** @type {import('#client').Effect} */ (current_effect).dom = current;

@ -64,7 +64,7 @@ export { proxy, unstate } from './client/proxy.js';
export { create_custom_element } from './client/dom/elements/custom-element.js';
export {
child,
child_frag,
first_child,
sibling,
$window as window,
$document as document

@ -9,7 +9,7 @@ export default function Bind_this($$anchor, $$props) {
/* Init */
var fragment = $.comment($$anchor);
var node = $.child_frag(fragment);
var node = $.first_child(fragment);
$.bind_this(Foo(node, {}), ($$value) => foo = $$value, () => foo);
$.close_frag($$anchor, fragment);

@ -13,7 +13,7 @@ export default function Main($$anchor, $$props) {
let y = () => 'test';
/* Init */
var fragment = $.open_frag($$anchor, frag, false);
var div = $.child_frag(fragment);
var div = $.first_child(fragment);
var svg = $.sibling($.sibling(div, true));
var custom_element = $.sibling($.sibling(svg, true));
var div_1 = $.sibling($.sibling(custom_element, true));

@ -9,7 +9,7 @@ export default function Each_string_template($$anchor, $$props) {
/* Init */
var fragment = $.comment($$anchor);
var node = $.child_frag(fragment);
var node = $.first_child(fragment);
$.each_indexed(
node,

@ -15,7 +15,7 @@ export default function Function_prop_no_getter($$anchor, $$props) {
const plusOne = (num) => num + 1;
/* Init */
var fragment = $.comment($$anchor);
var node = $.child_frag(fragment);
var node = $.first_child(fragment);
Button(node, {
onmousedown: () => $.set(count, $.get(count) + 1),

@ -19,7 +19,7 @@ export default function State_proxy_literal($$anchor, $$props) {
let tpl = $.source(``);
/* Init */
var fragment = $.open_frag($$anchor, frag);
var input = $.child_frag(fragment);
var input = $.first_child(fragment);
$.remove_input_attr_defaults(input);

@ -9,7 +9,7 @@ export default function Svelte_element($$anchor, $$props) {
let tag = $.prop($$props, "tag", 3, 'hr');
/* Init */
var fragment = $.comment($$anchor);
var node = $.child_frag(fragment);
var node = $.first_child(fragment);
$.element(node, tag, false);
$.close_frag($$anchor, fragment);

Loading…
Cancel
Save