svelte
Version:
Cybernetically enhanced web apps
106 lines (87 loc) • 2.62 kB
JavaScript
/** @import { TemplateNode } from '#client' */
import {
HYDRATION_END,
HYDRATION_ERROR,
HYDRATION_START,
HYDRATION_START_ELSE
} from '../../../constants.js';
import * as w from '../warnings.js';
import { get_next_sibling } from './operations.js';
/**
* Use this variable to guard everything related to hydration code so it can be treeshaken out
* if the user doesn't use the `hydrate` method and these code paths are therefore not needed.
*/
export let hydrating = false;
/** @param {boolean} value */
export function set_hydrating(value) {
hydrating = value;
}
/**
* The node that is currently being hydrated. This starts out as the first node inside the opening
* <!--[--> comment, and updates each time a component calls `$.child(...)` or `$.sibling(...)`.
* When entering a block (e.g. `{#if ...}`), `hydrate_node` is the block opening comment; by the
* time we leave the block it is the closing comment, which serves as the block's anchor.
* @type {TemplateNode}
*/
export let hydrate_node;
/** @param {TemplateNode} node */
export function set_hydrate_node(node) {
if (node === null) {
w.hydration_mismatch();
throw HYDRATION_ERROR;
}
return (hydrate_node = node);
}
export function hydrate_next() {
return set_hydrate_node(/** @type {TemplateNode} */ (get_next_sibling(hydrate_node)));
}
/** @param {TemplateNode} node */
export function reset(node) {
if (!hydrating) return;
// If the node has remaining siblings, something has gone wrong
if (get_next_sibling(hydrate_node) !== null) {
w.hydration_mismatch();
throw HYDRATION_ERROR;
}
hydrate_node = node;
}
/**
* @param {HTMLTemplateElement} template
*/
export function hydrate_template(template) {
if (hydrating) {
// @ts-expect-error TemplateNode doesn't include DocumentFragment, but it's actually fine
hydrate_node = template.content;
}
}
export function next(count = 1) {
if (hydrating) {
var i = count;
var node = hydrate_node;
while (i--) {
node = /** @type {TemplateNode} */ (get_next_sibling(node));
}
hydrate_node = node;
}
}
/**
* Removes all nodes starting at `hydrate_node` up until the next hydration end comment
*/
export function remove_nodes() {
var depth = 0;
var node = hydrate_node;
while (true) {
if (node.nodeType === 8) {
var data = /** @type {Comment} */ (node).data;
if (data === HYDRATION_END) {
if (depth === 0) return node;
depth -= 1;
} else if (data === HYDRATION_START || data === HYDRATION_START_ELSE) {
depth += 1;
}
}
var next = /** @type {TemplateNode} */ (get_next_sibling(node));
node.remove();
node = next;
}
}