devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
232 lines (222 loc) • 8.45 kB
JavaScript
/**
* DevExtreme (esm/__internal/core/r1/runtime/inferno/mocked/hydrate.js)
* Version: 25.1.3
* Build date: Wed Jun 25 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import {
_CI,
_HI,
_M,
_MCCC,
_ME,
_MFCC,
_MP,
_MR,
EMPTY_OBJ,
render,
_RFC as renderFunctionalComponent,
AnimationQueues
} from "inferno";
import {
isFunction,
isInvalid,
isNull,
isNullOrUndef,
throwError
} from "./shared";
import {
ChildFlags,
VNodeFlags
} from "./vnode-flags";
function isSameInnerHTML(dom, innerHTML) {
const tempdom = document.createElement("i");
tempdom.innerHTML = innerHTML;
return tempdom.innerHTML === dom.innerHTML
}
function findLastDOMFromVNode(vNode) {
let flags;
let children;
while (vNode) {
flags = vNode.flags;
if (flags & VNodeFlags.DOMRef) {
return vNode.dom
}
children = vNode.children;
if (flags & VNodeFlags.Fragment) {
vNode = vNode.childFlags === ChildFlags.HasVNodeChildren ? children : children[children.length - 1]
} else if (flags & VNodeFlags.ComponentClass) {
vNode = children.$LI
} else {
vNode = children
}
}
return null
}
function isSamePropsInnerHTML(dom, props) {
return Boolean(props && props.dangerouslySetInnerHTML && props.dangerouslySetInnerHTML.__html && isSameInnerHTML(dom, props.dangerouslySetInnerHTML.__html))
}
function hydrateComponent(vNode, parentDOM, dom, context, isSVG, isClass, lifecycle, animations) {
const type = vNode.type;
const ref = vNode.ref;
const props = vNode.props || EMPTY_OBJ;
let currentNode;
if (isClass) {
const instance = _CI(vNode, type, props, context, isSVG, lifecycle);
const input = instance.$LI;
currentNode = hydrateVNode(input, parentDOM, dom, instance.$CX, isSVG, lifecycle, animations);
_MCCC(ref, instance, lifecycle, animations)
} else {
const input = _HI(renderFunctionalComponent(vNode, context));
currentNode = hydrateVNode(input, parentDOM, dom, context, isSVG, lifecycle, animations);
vNode.children = input;
_MFCC(vNode, lifecycle, animations)
}
return currentNode
}
function hydrateChildren(parentVNode, parentNode, currentNode, context, isSVG, lifecycle, animations) {
const childFlags = parentVNode.childFlags;
const children = parentVNode.children;
const props = parentVNode.props;
const flags = parentVNode.flags;
if (childFlags !== ChildFlags.HasInvalidChildren) {
if (childFlags === ChildFlags.HasVNodeChildren) {
if (isNull(currentNode)) {
_M(children, parentNode, context, isSVG, null, lifecycle, animations)
} else {
currentNode = hydrateVNode(children, parentNode, currentNode, context, isSVG, lifecycle, animations);
currentNode = currentNode ? currentNode.nextSibling : null
}
} else if (childFlags === ChildFlags.HasTextChildren) {
if (isNull(currentNode)) {
parentNode.appendChild(document.createTextNode(children))
} else if (1 !== parentNode.childNodes.length || 3 !== currentNode.nodeType) {
parentNode.textContent = children
} else if (currentNode.nodeValue !== children) {
currentNode.nodeValue = children
}
currentNode = null
} else if (childFlags & ChildFlags.MultipleChildren) {
let prevVNodeIsTextNode = false;
for (let i = 0, len = children.length; i < len; ++i) {
const child = children[i];
if (isNull(currentNode) || prevVNodeIsTextNode && (child.flags & VNodeFlags.Text) > 0) {
_M(child, parentNode, context, isSVG, currentNode, lifecycle, animations)
} else {
currentNode = hydrateVNode(child, parentNode, currentNode, context, isSVG, lifecycle, animations);
currentNode = currentNode ? currentNode.nextSibling : null
}
prevVNodeIsTextNode = (child.flags & VNodeFlags.Text) > 0
}
}
if (0 === (flags & VNodeFlags.Fragment)) {
let nextSibling = null;
while (currentNode) {
nextSibling = currentNode.nextSibling;
parentNode.removeChild(currentNode);
currentNode = nextSibling
}
}
} else if (!isNull(parentNode.firstChild) && !isSamePropsInnerHTML(parentNode, props)) {
parentNode.textContent = "";
if (flags & VNodeFlags.FormElement) {
parentNode.defaultValue = ""
}
}
}
function hydrateElement(vNode, parentDOM, dom, context, isSVG, lifecycle, animations) {
const props = vNode.props;
const className = vNode.className;
const flags = vNode.flags;
const ref = vNode.ref;
isSVG = isSVG || (flags & VNodeFlags.SvgElement) > 0;
if (1 !== dom.nodeType) {
_ME(vNode, null, context, isSVG, null, lifecycle, animations);
parentDOM.replaceChild(vNode.dom, dom)
} else {
vNode.dom = dom;
hydrateChildren(vNode, dom, dom.firstChild, context, isSVG, lifecycle, animations);
if (!isNull(props)) {
_MP(vNode, flags, props, dom, isSVG, animations)
}
if (isNullOrUndef(className)) {
if ("" !== dom.className) {
dom.removeAttribute("class")
}
} else if (isSVG) {
dom.setAttribute("class", className)
} else {
dom.className = className
}
_MR(ref, dom, lifecycle)
}
return vNode.dom
}
function hydrateText(vNode, parentDOM, dom) {
if (3 !== dom.nodeType) {
parentDOM.replaceChild(vNode.dom = document.createTextNode(vNode.children), dom)
} else {
const text = vNode.children;
if (dom.nodeValue !== text) {
dom.nodeValue = text
}
vNode.dom = dom
}
return vNode.dom
}
function hydrateFragment(vNode, parentDOM, dom, context, isSVG, lifecycle, animations) {
const children = vNode.children;
if (vNode.childFlags === ChildFlags.HasVNodeChildren) {
hydrateText(children, parentDOM, dom);
return children.dom
}
hydrateChildren(vNode, parentDOM, dom, context, isSVG, lifecycle, animations);
return findLastDOMFromVNode(children[children.length - 1])
}
function hydrateVNode(vNode, parentDOM, currentDom, context, isSVG, lifecycle, animations) {
const flags = vNode.flags |= VNodeFlags.InUse;
if (flags & VNodeFlags.Component) {
return hydrateComponent(vNode, parentDOM, currentDom, context, isSVG, (flags & VNodeFlags.ComponentClass) > 0, lifecycle, animations)
}
if (flags & VNodeFlags.Element) {
return hydrateElement(vNode, parentDOM, currentDom, context, isSVG, lifecycle, animations)
}
if (flags & VNodeFlags.Text) {
return hydrateText(vNode, parentDOM, currentDom)
}
if (flags & VNodeFlags.Void) {
return vNode.dom = currentDom
}
if (flags & VNodeFlags.Fragment) {
return hydrateFragment(vNode, parentDOM, currentDom, context, isSVG, lifecycle, animations)
}
throwError();
return null
}
export function hydrate(input, parentDOM, callback) {
let dom = parentDOM.firstChild;
if (isNull(dom)) {
render(input, parentDOM, callback)
} else {
const lifecycle = [];
const animations = new AnimationQueues;
if (!isInvalid(input)) {
dom = hydrateVNode(input, parentDOM, dom, {}, false, lifecycle, animations)
}
while (dom && (dom = dom.nextSibling)) {
parentDOM.removeChild(dom)
}
if (lifecycle.length > 0) {
let listener;
while (void 0 !== (listener = lifecycle.shift())) {
listener()
}
}
}
parentDOM.$V = input;
if (isFunction(callback)) {
callback()
}
}