|
|
@ -2,6 +2,7 @@
|
|
|
|
import { hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
|
|
|
|
import { hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
|
|
|
|
import { DEV } from 'esm-env';
|
|
|
|
import { DEV } from 'esm-env';
|
|
|
|
import { init_array_prototype_warnings } from '../dev/equality.js';
|
|
|
|
import { init_array_prototype_warnings } from '../dev/equality.js';
|
|
|
|
|
|
|
|
import { get_descriptor } from '../../shared/utils.js';
|
|
|
|
|
|
|
|
|
|
|
|
// export these for reference in the compiled code, making global name deduplication unnecessary
|
|
|
|
// export these for reference in the compiled code, making global name deduplication unnecessary
|
|
|
|
/** @type {Window} */
|
|
|
|
/** @type {Window} */
|
|
|
@ -10,6 +11,11 @@ export var $window;
|
|
|
|
/** @type {Document} */
|
|
|
|
/** @type {Document} */
|
|
|
|
export var $document;
|
|
|
|
export var $document;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {() => Node | null} */
|
|
|
|
|
|
|
|
var first_child_getter;
|
|
|
|
|
|
|
|
/** @type {() => Node | null} */
|
|
|
|
|
|
|
|
var next_sibling_getter;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Initialize these lazily to avoid issues when using the runtime in a server context
|
|
|
|
* Initialize these lazily to avoid issues when using the runtime in a server context
|
|
|
|
* where these globals are not available while avoiding a separate server entry point
|
|
|
|
* where these globals are not available while avoiding a separate server entry point
|
|
|
@ -23,6 +29,12 @@ export function init_operations() {
|
|
|
|
$document = document;
|
|
|
|
$document = document;
|
|
|
|
|
|
|
|
|
|
|
|
var element_prototype = Element.prototype;
|
|
|
|
var element_prototype = Element.prototype;
|
|
|
|
|
|
|
|
var node_prototype = Node.prototype;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
first_child_getter = get_descriptor(node_prototype, 'firstChild').get;
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
next_sibling_getter = get_descriptor(node_prototype, 'nextSibling').get;
|
|
|
|
|
|
|
|
|
|
|
|
// the following assignments improve perf of lookups on DOM nodes
|
|
|
|
// the following assignments improve perf of lookups on DOM nodes
|
|
|
|
// @ts-expect-error
|
|
|
|
// @ts-expect-error
|
|
|
@ -53,6 +65,24 @@ export function create_text(value = '') {
|
|
|
|
return document.createTextNode(value);
|
|
|
|
return document.createTextNode(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @template {Node} N
|
|
|
|
|
|
|
|
* @param {N} node
|
|
|
|
|
|
|
|
* @returns {Node | null}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
export function get_first_child(node) {
|
|
|
|
|
|
|
|
return first_child_getter.call(node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @template {Node} N
|
|
|
|
|
|
|
|
* @param {N} node
|
|
|
|
|
|
|
|
* @returns {Node | null}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
export function get_next_sibling(node) {
|
|
|
|
|
|
|
|
return next_sibling_getter.call(node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
|
|
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
|
|
* @template {Node} N
|
|
|
|
* @template {Node} N
|
|
|
@ -61,10 +91,10 @@ export function create_text(value = '') {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function child(node) {
|
|
|
|
export function child(node) {
|
|
|
|
if (!hydrating) {
|
|
|
|
if (!hydrating) {
|
|
|
|
return node.firstChild;
|
|
|
|
return get_first_child(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var child = /** @type {TemplateNode} */ (hydrate_node.firstChild);
|
|
|
|
var child = /** @type {TemplateNode} */ (get_first_child(hydrate_node));
|
|
|
|
|
|
|
|
|
|
|
|
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty
|
|
|
|
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty
|
|
|
|
if (child === null) {
|
|
|
|
if (child === null) {
|
|
|
@ -84,10 +114,10 @@ export function child(node) {
|
|
|
|
export function first_child(fragment, is_text) {
|
|
|
|
export function first_child(fragment, is_text) {
|
|
|
|
if (!hydrating) {
|
|
|
|
if (!hydrating) {
|
|
|
|
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
|
|
|
|
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
|
|
|
|
var first = /** @type {DocumentFragment} */ (fragment).firstChild;
|
|
|
|
var first = /** @type {DocumentFragment} */ (get_first_child(/** @type {Node} */ (fragment)));
|
|
|
|
|
|
|
|
|
|
|
|
// TODO prevent user comments with the empty string when preserveComments is true
|
|
|
|
// TODO prevent user comments with the empty string when preserveComments is true
|
|
|
|
if (first instanceof Comment && first.data === '') return first.nextSibling;
|
|
|
|
if (first instanceof Comment && first.data === '') return get_next_sibling(first);
|
|
|
|
|
|
|
|
|
|
|
|
return first;
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -114,10 +144,10 @@ export function first_child(fragment, is_text) {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function sibling(node, is_text = false) {
|
|
|
|
export function sibling(node, is_text = false) {
|
|
|
|
if (!hydrating) {
|
|
|
|
if (!hydrating) {
|
|
|
|
return /** @type {TemplateNode} */ (node.nextSibling);
|
|
|
|
return /** @type {TemplateNode} */ (get_next_sibling(node));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var next_sibling = /** @type {TemplateNode} */ (hydrate_node.nextSibling);
|
|
|
|
var next_sibling = /** @type {TemplateNode} */ (get_next_sibling(hydrate_node));
|
|
|
|
|
|
|
|
|
|
|
|
var type = next_sibling.nodeType;
|
|
|
|
var type = next_sibling.nodeType;
|
|
|
|
|
|
|
|
|
|
|
|