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

97.97% Statements 97/99
100% Branches 25/25
100% Functions 1/1
97.89% Lines 93/95

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 2x 2x 2x 2x 2x 2x 2x 844x 400x 400x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 844x 1555x 1395x 1395x 1395x 1395x 1555x 400x 400x 400x 2x 2x 2x 2x 2x 2x 2x 2x 400x 1395x 1555x 702x 53x 702x 649x 649x 701x 702x 29x   29x 29x 1555x 693x 2x 693x 160x 160x 693x 693x 274x   274x 274x 693x 1231x 1555x 2x 2x 2x 844x 844x 844x 400x 400x 844x  
/** @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;
	}
}