All files / src/internal/client/dom hydration.js

100% Statements 91/91
100% Branches 19/19
100% Functions 3/3
100% Lines 88/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 892x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4487x 4487x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1546x 1546x 1546x 2x 2x 2x 2x 2x 2x 2x 2x 2x 12773x 6212x 6212x 6561x 6561x 6561x 6561x 12773x 8x 8x 6553x 6553x 6553x 6553x 6553x 12773x 39819x 26636x 26636x 26636x 9991x 26636x 16542x 6551x 6551x 6551x 6551x 9991x 9991x 9991x 26636x 33268x 33268x 33268x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 2x 2x 2x 2x  
import { DEV } from 'esm-env';
import { HYDRATION_END, HYDRATION_START, HYDRATION_ERROR } from '../../../constants.js';
import * as w from '../warnings.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;
}
 
/**
 * Array of nodes to traverse for hydration. This will be null if we're not hydrating, but for
 * the sake of simplicity we're not going to use `null` checks everywhere and instead rely on
 * the `hydrating` flag to tell whether or not we're in hydration mode at which point this is set.
 * @type {import('#client').TemplateNode[]}
 */
export let hydrate_nodes = /** @type {any} */ (null);
 
/** @type {import('#client').TemplateNode} */
export let hydrate_start;
 
/** @param {import('#client').TemplateNode[]} nodes */
export function set_hydrate_nodes(nodes) {
	hydrate_nodes = nodes;
	hydrate_start = nodes && nodes[0];
}
 
/**
 * This function is only called when `hydrating` is true. If passed a `<!--[-->` opening
 * hydration marker, it finds the corresponding closing marker and sets `hydrate_nodes`
 * to everything between the markers, before returning the closing marker.
 * @param {Node} node
 * @returns {Node}
 */
export function hydrate_anchor(node) {
	if (node.nodeType !== 8) {
		return node;
	}
 
	var current = /** @type {Node | null} */ (node);
 
	// TODO this could have false positives, if a user comment consisted of `[`. need to tighten that up
	if (/** @type {Comment} */ (current).data !== HYDRATION_START) {
		return node;
	}
 
	/** @type {Node[]} */
	var nodes = [];
	var depth = 0;
 
	while ((current = /** @type {Node} */ (current).nextSibling) !== null) {
		if (current.nodeType === 8) {
			var data = /** @type {Comment} */ (current).data;
 
			if (data === HYDRATION_START) {
				depth += 1;
			} else if (data[0] === HYDRATION_END) {
				if (depth === 0) {
					hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes);
					hydrate_start = /** @type {import('#client').TemplateNode} */ (nodes[0]);
					return current;
				}
 
				depth -= 1;
			}
		}
 
		nodes.push(current);
	}
 
	let location;
 
	if (DEV) {
		// @ts-expect-error
		const loc = node.parentNode?.__svelte_meta?.loc;
		if (loc) {
			location = `${loc.file}:${loc.line}:${loc.column}`;
		}
	}
 
	w.hydration_mismatch(location);
	throw HYDRATION_ERROR;
}