All files / src/internal/server dev.js

97.67% Statements 84/86
72.72% Branches 8/11
100% Functions 5/5
97.67% Lines 84/86

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 901x 1x       1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 1x 1x 2803x 2803x 1x 1x 1x 1x 1x 1x 1x 1x 158x 158x 158x 158x 25x 25x 25x 25x 3x 3x 25x 25x 4x 4x     4x 4x 25x 158x 158x 158x 1x 1x 156x 156x  
/** @import { Component, Payload } from '#server' */
import { FILENAME } from '../../constants.js';
import {
	is_tag_valid_with_ancestor,
	is_tag_valid_with_parent
} from '../../html-tree-validation.js';
import { current_component } from './context.js';
 
/**
 * @typedef {{
 * 	tag: string;
 * 	parent: null | Element;
 *  filename: null | string;
 *  line: number;
 *  column: number;
 * }} Element
 */
 
/**
 * @type {Element | null}
 */
let parent = null;
 
/** @type {Set<string>} */
let seen;
 
/**
 * @param {Element} element
 */
function stringify(element) {
	if (element.filename === null) return `\`<${element.tag}>\``;
	return `\`<${element.tag}>\` (${element.filename}:${element.line}:${element.column})`;
}
 
/**
 * @param {Payload} payload
 * @param {Element} parent
 * @param {Element} child
 */
function print_error(payload, parent, child) {
	var message =
		`node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n` +
		'This can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.';
 
	if ((seen ??= new Set()).has(message)) return;
	seen.add(message);
 
	// eslint-disable-next-line no-console
	console.error(message);
	payload.head.out += `<script>console.error(${JSON.stringify(message)})</script>`;
}
 
export function reset_elements() {
	parent = null;
}
 
/**
 * @param {Payload} payload
 * @param {string} tag
 * @param {number} line
 * @param {number} column
 */
export function push_element(payload, tag, line, column) {
	var filename = /** @type {Component} */ (current_component).function[FILENAME];
	var child = { tag, parent, filename, line, column };
 
	if (parent !== null) {
		var ancestor = parent.parent;
		var ancestors = [parent.tag];
 
		if (!is_tag_valid_with_parent(tag, parent.tag)) {
			print_error(payload, parent, child);
		}
 
		while (ancestor != null) {
			ancestors.push(ancestor.tag);
			if (!is_tag_valid_with_ancestor(tag, ancestors)) {
				print_error(payload, ancestor, child);
			}
			ancestor = ancestor.parent;
		}
	}
 
	parent = child;
}
 
export function pop_element() {
	parent = /** @type {Element} */ (parent).parent;
}