if (!isHydrating) {
if (_insertionParent) insert(frag, _insertionParent, _insertionAnchor)
} else {
- // if _insertionAnchor is defined, insertionParent contains a static node
- // that should be skipped during hydration.
- // Advance to the next sibling node of parent to skip the static node.
+ // After block node hydration is completed, advance currentHydrationNode to
+ // _insertionParent's next sibling if _insertionAnchor has a value
+ // _insertionAnchor values:
+ // 1. Node type: _insertionAnchor is a static node, no hydration needed
+ // 2. null: block node is appended, potentially without next sibling
+ // 3. 0: next sibling of current block node is static, no hydration needed
if (_insertionAnchor !== undefined) {
advanceHydrationNode(_insertionParent!)
}
locateHydrationNode = locateHydrationNodeImpl
// optimize anchor cache lookup
;(Comment.prototype as any).$fe = undefined
- ;(Node.prototype as any).$ps = undefined
- ;(Node.prototype as any).$pa = undefined
- ;(Node.prototype as any).$ia = undefined
- ;(Node.prototype as any).$aa = undefined
+ ;(Node.prototype as any).$pns = undefined
+ ;(Node.prototype as any).$lpn = undefined
+ ;(Node.prototype as any).$lin = undefined
+ ;(Node.prototype as any).$lan = undefined
isOptimized = true
}
enableHydrationNodeLookup()
currentHydrationNode = node
}
-function findParentSibling(n: Node): Node | null {
+function locateNextSiblingOfParent(n: Node): Node | null {
if (!n.parentNode) return null
- return n.parentNode.nextSibling || findParentSibling(n.parentNode)
+ return n.parentNode.nextSibling || locateNextSiblingOfParent(n.parentNode)
}
-export function advanceHydrationNode(node: Node & { $ps?: Node | null }): void {
+export function advanceHydrationNode(
+ node: Node & { $pns?: Node | null },
+): void {
// if no next sibling, find the next node in the parent chain
const ret =
- node.nextSibling || node.$ps || (node.$ps = findParentSibling(node))
+ node.nextSibling ||
+ // pns is short for "parent next sibling"
+ node.$pns ||
+ (node.$pns = locateNextSiblingOfParent(node))
if (ret) setCurrentHydrationNode(ret)
}
let node: Node | null
if (insertionAnchor === 0) {
// prepend
- node = insertionParent!.$pa = locateHydrationNodeByAnchor(
- insertionParent!.$pa || _child(insertionParent!),
+ node = insertionParent!.$lpn = locateHydrationNodeByAnchor(
+ insertionParent!.$lpn || _child(insertionParent!),
BLOCK_PREPEND_ANCHOR_LABEL,
)!
} else if (insertionAnchor) {
- // insertion anchor
- node = insertionParent!.$ia = locateHydrationNodeByAnchor(
- insertionParent!.$ia || _child(insertionParent!),
+ // insert
+ node = insertionParent!.$lin = locateHydrationNodeByAnchor(
+ insertionParent!.$lin || _child(insertionParent!),
BLOCK_INSERTION_ANCHOR_LABEL,
)!
} else if (insertionAnchor === null) {
- // append anchor
- node = insertionParent!.$aa = locateHydrationNodeByAnchor(
- insertionParent!.$aa || _child(insertionParent!),
+ // append
+ node = insertionParent!.$lan = locateHydrationNodeByAnchor(
+ insertionParent!.$lan || _child(insertionParent!),
BLOCK_APPEND_ANCHOR_LABEL,
)!
} else {
return null
}
-export function locateVaporFragmentAnchor(
+export function locateFragmentAnchor(
node: Node,
- anchorLabel: string,
+ label: string,
): Comment | null {
- while (node) {
- if (isComment(node, anchorLabel)) return node
+ while (node && node.nodeType === 8) {
+ if (isComment(node, label)) return node
node = node.nextSibling!
}
return null
}
-function locateHydrationNodeByAnchor(
- node: Node,
- anchorLabel: string,
-): Node | null {
+function locateHydrationNodeByAnchor(node: Node, label: string): Node | null {
while (node) {
- if (isComment(node, `[${anchorLabel}`)) return node.nextSibling
+ if (isComment(node, `[${label}`)) return node.nextSibling
node = node.nextSibling!
}
if (__DEV__) {
throw new Error(
- `Could not locate hydration node with anchor label: ${anchorLabel}`,
+ `Could not locate hydration node with anchor label: ${label}`,
)
}
return null
}
-export function skipBlockNodes(node: Node): Node {
+export function advanceToNonBlockNode(node: Node): Node {
while (node) {
if (isComment(node, `[${BLOCK_PREPEND_ANCHOR_LABEL}`)) {
node = locateEndAnchor(
currentHydrationNode,
isComment,
isHydrating,
+ locateFragmentAnchor,
locateHydrationNode,
- locateVaporFragmentAnchor,
setCurrentHydrationNode,
hydrateNode as vaporHydrateNode,
} from './dom/hydration'
const propsRef = (vnode.vs!.ref = shallowRef(vnode.props))
vaporHydrateNode(node, () => {
vnode.vb = slot(new Proxy(propsRef, vaporSlotPropsProxyHandler))
- vnode.el = vnode.anchor = locateVaporFragmentAnchor(
+ vnode.el = vnode.anchor = locateFragmentAnchor(
currentHydrationNode!,
- // there is not vapor slot anchor (<!--slot-->) injected in vdom component,
- // so here use the fragment end anchor label
+ // locate the vdom fragment end anchor (<!--]-->), since no vapor slot
+ // anchor (<!--slot-->) is injected in vdom component
']',
)
- if (
- (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
- !vnode.anchor
- ) {
+ if (__DEV__ && !vnode.anchor) {
throw new Error(`vapor slot anchor node was not found.`)
}
})
if (isValidSlot) {
if (isHydrating) {
// if slot content is a vnode, hydrate it
- // otherwise, it is a vapor Block that is already hydrated during
+ // otherwise, it's a vapor Block that was already hydrated during
// renderSlot
if (isVNode(vnode)) {
hydrateVNode(vnode!, parentComponent as any)