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

100% Statements 95/95
100% Branches 14/14
100% Functions 4/4
100% Lines 89/89

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 902x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 92x 92x 92x 92x 92x 92x 92x 92x 92x 110x 105x 110x 14x 14x 14x 105x 105x 105x 105x 92x 92x 92x 44x 44x 92x 2x 2x 2x 2x 2x 2x 2x 2x 37x 36x 36x 36x 36x 36x 36x 36x 36x 37x 37x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4x 4x 4x 2x 2x 2x 2x 2x 2x 2x 4x 4x 4x 4x 4x 4x  
/** @import { Effect, TemplateNode } from '#client' */
import { add_snippet_symbol } from '../../../shared/validate.js';
import { EFFECT_TRANSPARENT } from '../../constants.js';
import { branch, block, destroy_effect } from '../../reactivity/effects.js';
import {
	dev_current_component_function,
	set_dev_current_component_function
} from '../../runtime.js';
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
import { assign_nodes } from '../template.js';
 
/**
 * @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
 * @param {TemplateNode} node
 * @param {() => SnippetFn | null | undefined} get_snippet
 * @param {(() => any)[]} args
 * @returns {void}
 */
export function snippet(node, get_snippet, ...args) {
	var anchor = node;
 
	/** @type {SnippetFn | null | undefined} */
	var snippet;
 
	/** @type {Effect | null} */
	var snippet_effect;
 
	block(() => {
		if (snippet === (snippet = get_snippet())) return;
 
		if (snippet_effect) {
			destroy_effect(snippet_effect);
			snippet_effect = null;
		}
 
		if (snippet) {
			snippet_effect = branch(() => /** @type {SnippetFn} */ (snippet)(anchor, ...args));
		}
	}, EFFECT_TRANSPARENT);
 
	if (hydrating) {
		anchor = hydrate_node;
	}
}
 
/**
 * In development, wrap the snippet function so that it passes validation, and so that the
 * correct component context is set for ownership checks
 * @param {any} component
 * @param {(node: TemplateNode, ...args: any[]) => void} fn
 */
export function wrap_snippet(component, fn) {
	return add_snippet_symbol((/** @type {TemplateNode} */ node, /** @type {any[]} */ ...args) => {
		var previous_component_function = dev_current_component_function;
		set_dev_current_component_function(component);
 
		try {
			return fn(node, ...args);
		} finally {
			set_dev_current_component_function(previous_component_function);
		}
	});
}
 
/**
 * Create a snippet imperatively using mount, hyrdate and render functions.
 * @param {{
 * 	 mount: (...params: any[]) => Element,
 *   hydrate?: (element: Element, ...params: any[]) => void,
 *   render: (...params: any[]) => string
 * }} options
 */
export function createRawSnippet({ mount, hydrate }) {
	var snippet_fn = (/** @type {TemplateNode} */ anchor, /** @type {any[]} */ ...params) => {
		var element;
		if (hydrating) {
			element = hydrate_node;
			hydrate_next();
			if (hydrate !== undefined) hydrate(/** @type {Element} */ (element), ...params);
		} else {
			element = mount(...params);
			anchor.before(element);
		}
		assign_nodes(element, element);
	};
	add_snippet_symbol(snippet_fn);
 
	return snippet_fn;
}