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

100% Statements 103/103
100% Branches 27/27
100% Functions 4/4
100% Lines 99/99

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 89 90 91 92 93 94 95 96 97 98 99 1002x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4455x 4455x 2x 2x 2x 2x 2x 2x 2x 2x 1482x 1482x 2x 2x 2x 2x 2x 2x 2x 2x 12786x 12786x 6188x 6188x 6598x 6598x 6598x 6598x 6598x 6598x 6598x 6598x 12786x 39956x 26724x 26724x 26724x 10012x 26724x 16608x 6596x 6596x 10012x 10012x 10012x 26724x 33360x 33360x 33360x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 2x 2x 2x 2x 2x 2x 28x 28x 28x 28x 28x 40x 33x 33x 33x 2x 33x 30x 2x 2x 33x 12x 12x 12x 12x 12x 28x  
import { DEV } from 'esm-env';
import { HYDRATION_END, HYDRATION_START, HYDRATION_ERROR } from '../../../constants.js';
import * as w from '../warnings.js';
import { remove_nodes } 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;
}
 
/** @type {import('#client').TemplateNode} */
export let hydrate_start = /** @type {any} */ (null);
 
/**
 * @param {import('#client').TemplateNode} start
 */
export function set_hydrate_nodes(start) {
	hydrate_start = start;
}
 
/**
 * This function is only called when `hydrating` is true. If passed a `<!--[-->` opening
 * hydration marker, it sets `hydrate_start` to be the next node and returns the closing marker
 * @param {Node} node
 * @returns {Node}
 */
export function hydrate_anchor(node) {
	// TODO this could have false positives, if a user comment consisted of `[`. need to tighten that up
	if (node.nodeType !== 8 || /** @type {Comment} */ (node).data !== HYDRATION_START) {
		return node;
	}
 
	hydrate_start = /** @type {import('#client').TemplateNode} */ (
		/** @type {Comment} */ (node).nextSibling
	);
 
	var current = hydrate_start;
	var depth = 0;
 
	while (current !== 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) {
					return current;
				}
 
				depth -= 1;
			}
		}
 
		current = /** @type {import('#client').TemplateNode} */ (current.nextSibling);
	}
 
	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;
}
 
export function remove_hydrate_nodes() {
	/** @type {import('#client').TemplateNode | null} */
	var node = hydrate_start;
	var depth = 0;
 
	while (node) {
		if (node.nodeType === 8) {
			var data = /** @type {Comment} */ (node).data;
 
			if (data === HYDRATION_START) {
				depth += 1;
			} else if (data[0] === HYDRATION_END) {
				if (depth === 0) return;
				depth -= 1;
			}
		}
 
		var next = /** @type {import('#client').TemplateNode | null} */ (node.nextSibling);
		node.remove();
		node = next;
	}
}