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

98.85% Statements 86/87
95.83% Branches 23/24
100% Functions 1/1
98.78% Lines 81/82

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 832x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 840x 1788x 1544x 1544x 1544x 1544x 1788x 384x 384x 384x 2x 2x 2x 2x 2x 2x 384x 1544x 1788x 789x 44x 789x 745x 745x 788x 789x 58x 56x 58x 58x 1788x 755x   755x 200x 200x 755x 755x 336x 272x 336x 336x 755x 1543x 1788x 2x 2x 2x 840x 840x  
import { EFFECT_TRANSPARENT } from '../../constants.js';
import { hydrate_nodes, hydrating, set_hydrating } from '../hydration.js';
import { remove } from '../reconciler.js';
import { block, branch, pause_effect, resume_effect } from '../../reactivity/effects.js';
import { HYDRATION_END_ELSE } from '../../../../constants.js';
 
/**
 * @param {Comment} anchor
 * @param {() => boolean} get_condition
 * @param {(anchor: Node) => import('#client').Dom} consequent_fn
 * @param {null | ((anchor: Node) => import('#client').Dom)} [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(
	anchor,
	get_condition,
	consequent_fn,
	alternate_fn = null,
	elseif = false
) {
	/** @type {import('#client').Effect | null} */
	var consequent_effect = null;
 
	/** @type {import('#client').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 = anchor.data === HYDRATION_END_ELSE;
 
			if (condition === is_else) {
				// Hydration mismatch: remove everything inside the anchor and start fresh.
				// This could happen with `{#if browser}...{/if}`, for example
				remove(hydrate_nodes);
				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);
}