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 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 856x 1816x 1572x 1572x 1572x 1572x 1816x 388x 388x 388x 2x 2x 2x 2x 2x 2x 388x 1572x 1816x 801x 44x 801x 757x 757x 800x 801x 58x 56x 58x 58x 1816x 771x   771x 200x 200x 771x 771x 342x 278x 342x 342x 771x 1571x 1816x 2x 2x 2x 856x 856x  
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);
}