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 12773x 12773x 6188x 6188x 6585x 6585x 6585x 6585x 6585x 6585x 6585x 6585x 12773x 39852x 26659x 26659x 26659x 9986x 26659x 16569x 6583x 6583x 9986x 9986x 9986x 26659x 33269x 33269x 33269x 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;
	}
}