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

100% Statements 103/103
100% Branches 26/26
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 12781x 12781x 6118x 6118x 6663x 6663x 6663x 6663x 6663x 6663x 6663x 6663x 12781x 40158x 26874x 26874x 26874x 10106x 26874x 16767x 6661x 6661x 10106x 10106x 10106x 26874x 33497x 33497x 33497x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 2x 2x 2x 2x 2x 2x 28x 28x 28x 28x 28x 36x 32x 32x 32x 2x 32x 30x 2x 2x 32x 8x 8x 8x 8x 8x 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;
	}
}