return node
}
-function nextNode(node: Node): Node | null {
+export function locateNextNode(node: Node): Node | null {
return isComment(node, '[')
- ? locateEndAnchor(node as Anchor)!.nextSibling
- : node.nextSibling
+ ? _next(locateEndAnchor(node)!)
+ : isComment(node, 'teleport start')
+ ? _next(locateEndAnchor(node, 'teleport start', 'teleport end')!)
+ : _next(node)
}
function locateHydrationNodeImpl(): void {
// prepend
if (insertionAnchor === 0) {
node = insertionParent!.$lpn = lastPrepend
- ? nextNode(lastPrepend)
+ ? locateNextNode(lastPrepend)
: firstChild
}
// insert
else if (insertionAnchor instanceof Node) {
const { $lin: lastInsertedNode } = insertionAnchor as ChildItem
node = (insertionAnchor as ChildItem).$lin = lastInsertedNode
- ? nextNode(lastInsertedNode)
+ ? locateNextNode(lastInsertedNode)
: insertionAnchor
}
// append
else {
node = insertionParent!.$lan = lastAppend
- ? nextNode(lastAppend)
+ ? locateNextNode(lastAppend)
: insertionAnchor === null
? firstChild
: locateChildByLogicalIndex(insertionParent!, insertionAnchor)!
return null
}
+export function locateFragmentEndAnchor(label: string = ']'): Comment | null {
+ let node = currentHydrationNode!
+ while (node) {
+ if (isComment(node, label)) return node
+ node = node.nextSibling!
+ }
+ return null
+}
function handleMismatch(node: Node, template: string): Node {
if (!isMismatchAllowed(node.parentElement!, MismatchTypes.CHILDREN)) {
currentHydrationNode,
isComment,
isHydrating,
+ locateFragmentEndAnchor,
locateHydrationNode,
} from './dom/hydration'
import {
// avoid repeated hydration during fallback rendering
if (this.anchor) return
- // reuse the empty comment node as the anchor for empty if
- // e.g. `<div v-if="false"></div>` -> `<!---->`
- if (this.anchorLabel === 'if' && isEmpty) {
- this.anchor = currentHydrationNode!
- if (!this.anchor) {
- throw new Error('Failed to locate if anchor')
- } else {
- if (__DEV__) {
- ;(this.anchor as Comment).data = this.anchorLabel
+ if (this.anchorLabel === 'if') {
+ // reuse the empty comment node as the anchor for empty if
+ // e.g. `<div v-if="false"></div>` -> `<!---->`
+ if (isEmpty) {
+ this.anchor = locateFragmentEndAnchor('')!
+ if (!this.anchor) {
+ throw new Error('Failed to locate if anchor')
+ } else {
+ if (__DEV__) {
+ ;(this.anchor as Comment).data = this.anchorLabel
+ }
+ return
}
- return
}
- }
-
- if (this.anchorLabel === 'slot') {
+ } else if (this.anchorLabel === 'slot') {
// reuse the empty comment node for empty slot
// e.g. `<slot v-if="false"></slot>`
if (isEmpty && isComment(currentHydrationNode!, '')) {
return
}
- // reuse the vdom fragment end anchor for slots
- this.anchor = currentHydrationNode!
+ // reuse the vdom fragment end anchor
+ this.anchor = locateFragmentEndAnchor()!
if (!this.anchor) {
throw new Error('Failed to locate slot anchor')
} else {