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

100% Statements 99/99
100% Branches 25/25
100% Functions 1/1
100% Lines 93/93

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 100 1012x 2x               2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 893x 406x 406x 893x 893x 893x 893x 893x 893x 893x 893x 893x 893x 893x 893x 893x 893x 1663x 1663x 1663x 1663x 1663x 1663x 1663x 1663x 1663x 1663x 406x 406x 406x 1x 1x 1x 1x 1x 1x 1x 1x 406x 1663x 1663x 833x 50x 833x 783x 783x 832x 833x 58x 54x 58x 58x 1663x 830x 2x 830x 198x 198x 830x 830x 377x 287x 377x 377x 830x 1662x 1663x 1x 1x 1x 893x 893x 893x 406x 406x 893x  
/** @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';
import { get } from '../../runtime.js';
import { derived } from '../../reactivity/deriveds.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;
 
	var derived_condition = derived(() => !!get_condition());
 
	var flags = elseif ? EFFECT_TRANSPARENT : 0;
 
	block(() => {
		// We use a derived here to ensure stability of any depedencies that are captured when we read `get_condition`.
		// This is mainly because the current block effect's dependencies are only applied _after_ the effect has finished
		// running, however as we're sync calling `destroy_effect` via `pause_effect` below, it might mean that our
		// dependencies get lost. By having a derived already having run, those dependencies won't be affected by this
		var condition = get(derived_condition);
 
		/** 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;
	}
}