All files / src/internal/client/dom/blocks if.js

100% Statements 92/92
100% Branches 27/27
100% Functions 1/1
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 89 90 91 92 93 94 95 962x 2x               2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 882x 401x 401x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 882x 1879x 1637x 1637x 1637x 1637x 1879x 401x 401x 401x 1x 1x 1x 1x 1x 1x 1x 1x 401x 1637x 1879x 835x 50x 835x 785x 785x 834x 835x 58x 54x 58x 58x 1879x 802x 2x 802x 198x 198x 802x 802x 358x 284x 358x 358x 802x 1636x 1879x 1x 1x 1x 882x 882x 882x 401x 401x 882x  
/** @import { Effect, TemplateNode } from '#client' */
import { EFFECT_TRANSPARENT } from '../../constants.js';
import {
	hydrate_next,
	hydrate_node,
	hydrating,
	remove_nodes,
	set_hydrate_node,
	set_hydrating
} from '../hydration.js';
import { block, branch, pause_effect, resume_effect } from '../../reactivity/effects.js';
import { HYDRATION_START_ELSE } from '../../../../constants.js';
 
/**
 * @param {TemplateNode} node
 * @param {() => boolean} get_condition
 * @param {(anchor: Node) => void} consequent_fn
 * @param {null | ((anchor: Node) => void)} [alternate_fn]
 * @param {boolean} [elseif] True if this is an `{:else if ...}` block rather than an `{#if ...}`, as that affects which transitions are considered 'local'
 * @returns {void}
 */
export function if_block(node, get_condition, consequent_fn, alternate_fn = null, elseif = false) {
	if (hydrating) {
		hydrate_next();
	}
 
	var anchor = node;
 
	/** @type {Effect | null} */
	var consequent_effect = null;
 
	/** @type {Effect | null} */
	var alternate_effect = null;
 
	/** @type {boolean | null} */
	var condition = null;
 
	var flags = elseif ? EFFECT_TRANSPARENT : 0;
 
	block(() => {
		if (condition === (condition = !!get_condition())) return;
 
		/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
		let mismatch = false;
 
		if (hydrating) {
			const is_else = /** @type {Comment} */ (anchor).data === HYDRATION_START_ELSE;
 
			if (condition === is_else) {
				// Hydration mismatch: remove everything inside the anchor and start fresh.
				// This could happen with `{#if browser}...{/if}`, for example
				anchor = remove_nodes();
 
				set_hydrate_node(anchor);
				set_hydrating(false);
				mismatch = true;
			}
		}
 
		if (condition) {
			if (consequent_effect) {
				resume_effect(consequent_effect);
			} else {
				consequent_effect = branch(() => consequent_fn(anchor));
			}
 
			if (alternate_effect) {
				pause_effect(alternate_effect, () => {
					alternate_effect = null;
				});
			}
		} else {
			if (alternate_effect) {
				resume_effect(alternate_effect);
			} else if (alternate_fn) {
				alternate_effect = branch(() => alternate_fn(anchor));
			}
 
			if (consequent_effect) {
				pause_effect(consequent_effect, () => {
					consequent_effect = null;
				});
			}
		}
 
		if (mismatch) {
			// continue in hydration mode
			set_hydrating(true);
		}
	}, flags);
 
	if (hydrating) {
		anchor = hydrate_node;
	}
}