chore: replace `hydrate_nodes[0]` with `hydrate_start` where possible (#11758)

* manipulate effect.dom rather than hydrate_nodes

* use hydrate_start instead of hydrate_nodes where possible

* tidy up
pull/11759/head
Rich Harris 7 months ago committed by GitHub
parent 196d7e41b1
commit a2260940e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,5 +1,5 @@
import { namespace_svg } from '../../../../constants.js'; import { namespace_svg } from '../../../../constants.js';
import { hydrate_anchor, hydrate_nodes, hydrating } from '../hydration.js'; import { hydrate_anchor, hydrate_start, hydrating } from '../hydration.js';
import { empty } from '../operations.js'; import { empty } from '../operations.js';
import { render_effect } from '../../reactivity/effects.js'; import { render_effect } from '../../reactivity/effects.js';
@ -19,7 +19,7 @@ export function css_props(anchor, is_html, props, component) {
if (hydrating) { if (hydrating) {
// Hydration: css props element is surrounded by a ssr comment ... // Hydration: css props element is surrounded by a ssr comment ...
element = /** @type {HTMLElement | SVGElement} */ (hydrate_nodes[0]); element = /** @type {HTMLElement | SVGElement} */ (hydrate_start);
// ... and the child(ren) of the css props element is also surround by a ssr comment // ... and the child(ren) of the css props element is also surround by a ssr comment
component_anchor = /** @type {Comment} */ ( component_anchor = /** @type {Comment} */ (
hydrate_anchor(/** @type {Comment} */ (element.firstChild)) hydrate_anchor(/** @type {Comment} */ (element.firstChild))

@ -8,7 +8,13 @@ import {
HYDRATION_END_ELSE, HYDRATION_END_ELSE,
HYDRATION_START HYDRATION_START
} from '../../../../constants.js'; } from '../../../../constants.js';
import { hydrate_anchor, hydrate_nodes, hydrating, set_hydrating } from '../hydration.js'; import {
hydrate_anchor,
hydrate_nodes,
hydrate_start,
hydrating,
set_hydrating
} from '../hydration.js';
import { clear_text_content, empty } from '../operations.js'; import { clear_text_content, empty } from '../operations.js';
import { remove } from '../reconciler.js'; import { remove } from '../reconciler.js';
import { untrack } from '../../runtime.js'; import { untrack } from '../../runtime.js';
@ -148,7 +154,7 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback
// this is separate to the previous block because `hydrating` might change // this is separate to the previous block because `hydrating` might change
if (hydrating) { if (hydrating) {
/** @type {Node} */ /** @type {Node} */
var child_anchor = hydrate_nodes[0]; var child_anchor = hydrate_start;
/** @type {import('#client').EachItem | import('#client').EachState} */ /** @type {import('#client').EachItem | import('#client').EachState} */
var prev = state; var prev = state;

@ -1,5 +1,5 @@
import { namespace_svg } from '../../../../constants.js'; import { namespace_svg } from '../../../../constants.js';
import { hydrate_anchor, hydrate_nodes, hydrating, set_hydrate_nodes } from '../hydration.js'; import { hydrate_anchor, hydrate_start, hydrating, set_hydrate_nodes } from '../hydration.js';
import { empty } from '../operations.js'; import { empty } from '../operations.js';
import { import {
block, block,
@ -79,7 +79,7 @@ export function element(anchor, get_tag, is_svg, render_fn, get_namespace, locat
if (next_tag && next_tag !== current_tag) { if (next_tag && next_tag !== current_tag) {
effect = branch(() => { effect = branch(() => {
element = hydrating element = hydrating
? /** @type {Element} */ (hydrate_nodes[0]) ? /** @type {Element} */ (hydrate_start)
: ns : ns
? document.createElementNS(ns, next_tag) ? document.createElementNS(ns, next_tag)
: document.createElement(next_tag); : document.createElement(next_tag);

@ -21,9 +21,13 @@ export function set_hydrating(value) {
*/ */
export let hydrate_nodes = /** @type {any} */ (null); export let hydrate_nodes = /** @type {any} */ (null);
/** @type {import('#client').TemplateNode} */
export let hydrate_start;
/** @param {import('#client').TemplateNode[]} nodes */ /** @param {import('#client').TemplateNode[]} nodes */
export function set_hydrate_nodes(nodes) { export function set_hydrate_nodes(nodes) {
hydrate_nodes = nodes; hydrate_nodes = nodes;
hydrate_start = nodes && nodes[0];
} }
/** /**
@ -58,6 +62,7 @@ export function hydrate_anchor(node) {
} else if (data[0] === HYDRATION_END) { } else if (data[0] === HYDRATION_END) {
if (depth === 0) { if (depth === 0) {
hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes); hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes);
hydrate_start = /** @type {import('#client').TemplateNode} */ (nodes[0]);
return current; return current;
} }

@ -1,6 +1,7 @@
import { hydrate_anchor, hydrate_nodes, hydrating } from './hydration.js'; import { hydrate_anchor, hydrating } from './hydration.js';
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
import { init_array_prototype_warnings } from '../dev/equality.js'; import { init_array_prototype_warnings } from '../dev/equality.js';
import { current_effect } from '../runtime.js';
// We cache the Node and Element prototype methods, so that we can avoid doing // We cache the Node and Element prototype methods, so that we can avoid doing
// expensive prototype chain lookups. // expensive prototype chain lookups.
@ -96,14 +97,19 @@ export function first_child(fragment, is_text) {
} }
// when we _are_ hydrating, `fragment` is an array of nodes // when we _are_ hydrating, `fragment` is an array of nodes
const first_node = /** @type {import('#client').TemplateNode[]} */ (fragment)[0]; var first_node = /** @type {import('#client').TemplateNode[]} */ (fragment)[0];
// if an {expression} is empty during SSR, there might be no // if an {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one // text node to hydrate — we must therefore create one
if (is_text && first_node?.nodeType !== 3) { if (is_text && first_node?.nodeType !== 3) {
const text = empty(); var text = empty();
hydrate_nodes.unshift(text); var dom = /** @type {import('#client').TemplateNode[]} */ (
/** @type {import('#client').Effect} */ (current_effect).dom
);
dom.unshift(text);
first_node?.before(text); first_node?.before(text);
return text; return text;
} }
@ -127,14 +133,13 @@ export function sibling(node, is_text = false) {
// if a sibling {expression} is empty during SSR, there might be no // if a sibling {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one // text node to hydrate — we must therefore create one
if (is_text && next_sibling?.nodeType !== 3) { if (is_text && next_sibling?.nodeType !== 3) {
const text = empty(); var text = empty();
if (next_sibling) { var dom = /** @type {import('#client').TemplateNode[]} */ (
const index = hydrate_nodes.indexOf(/** @type {Text | Comment | Element} */ (next_sibling)); /** @type {import('#client').Effect} */ (current_effect).dom
hydrate_nodes.splice(index, 0, text); );
next_sibling.before(text);
} else { dom.unshift(text);
hydrate_nodes.push(text); next_sibling?.before(text);
}
return text; return text;
} }

@ -1,10 +1,9 @@
import { hydrate_nodes, hydrating } from './hydration.js'; import { hydrate_nodes, hydrate_start, hydrating } from './hydration.js';
import { empty } from './operations.js'; import { empty } from './operations.js';
import { create_fragment_from_html } from './reconciler.js'; import { create_fragment_from_html } from './reconciler.js';
import { current_effect } from '../runtime.js'; import { current_effect } from '../runtime.js';
import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../constants.js'; import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../constants.js';
import { effect } from '../reactivity/effects.js'; import { effect } from '../reactivity/effects.js';
import { is_array } from '../utils.js';
/** /**
* @template {import("#client").TemplateNode | import("#client").TemplateNode[]} T * @template {import("#client").TemplateNode | import("#client").TemplateNode[]} T
@ -36,7 +35,7 @@ export function template(content, flags) {
return () => { return () => {
if (hydrating) { if (hydrating) {
return push_template_node(is_fragment ? hydrate_nodes : hydrate_nodes[0]); return push_template_node(is_fragment ? hydrate_nodes : hydrate_start);
} }
if (!node) { if (!node) {
@ -88,7 +87,7 @@ export function ns_template(content, flags, ns = 'svg') {
return () => { return () => {
if (hydrating) { if (hydrating) {
return push_template_node(is_fragment ? hydrate_nodes : hydrate_nodes[0]); return push_template_node(is_fragment ? hydrate_nodes : hydrate_start);
} }
if (!node) { if (!node) {
@ -181,7 +180,7 @@ function run_scripts(node) {
export function text(anchor) { export function text(anchor) {
if (!hydrating) return empty(); if (!hydrating) return empty();
var node = hydrate_nodes[0]; var node = hydrate_start;
if (!node) { if (!node) {
// if an {expression} is empty during SSR, `hydrate_nodes` will be empty. // if an {expression} is empty during SSR, `hydrate_nodes` will be empty.

Loading…
Cancel
Save