Skip to content

Commit b8efc8b

Browse files
committed
chore: tweaks
1 parent a9496de commit b8efc8b

File tree

9 files changed

+133
-97
lines changed

9 files changed

+133
-97
lines changed

packages/compiler-ssr/src/ssrCodegenTransform.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ function shouldProcessChildAsDynamic(
410410
if (dynamicNodeCount === 2) {
411411
return prevDynamicCount > 0
412412
}
413-
// For three or more dynamic nodes, mark the intermediate node as dynamic
413+
// For three or more dynamic nodes, mark the middle nodes as dynamic
414414
else if (dynamicNodeCount >= 3) {
415415
return prevDynamicCount > 0 && nextDynamicCount > 0
416416
}

packages/runtime-core/src/hydration.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,13 @@ import {
2525
getEscapedCssVarName,
2626
includeBooleanAttr,
2727
isBooleanAttr,
28-
isDynamicAnchor,
2928
isKnownHtmlAttr,
3029
isKnownSvgAttr,
3130
isOn,
3231
isRenderableAttrValue,
3332
isReservedProp,
3433
isString,
35-
isVaporFragmentEndAnchor,
34+
isVaporAnchors,
3635
normalizeClass,
3736
normalizeStyle,
3837
stringifyStyle,
@@ -127,10 +126,8 @@ export function createHydrationFunctions(
127126

128127
function nextSibling(node: Node) {
129128
let n = next(node)
130-
// skip if:
131-
// - dynamic anchors (`<!--[[-->`, `<!--][-->`)
132-
// - vapor fragment end anchors (e.g. `<!--if-->`, `<!--for-->`)
133-
if (n && (isDynamicAnchor(n) || isVaporFragmentEndAnchor(n))) {
129+
// skip vapor mode specific anchors
130+
if (n && isVaporAnchors(n)) {
134131
n = next(n)
135132
}
136133
return n
@@ -162,7 +159,8 @@ export function createHydrationFunctions(
162159
slotScopeIds: string[] | null,
163160
optimized = false,
164161
): Node | null => {
165-
if (isDynamicAnchor(node) || isVaporFragmentEndAnchor(node)) {
162+
// skip vapor mode specific anchors
163+
if (isVaporAnchors(node)) {
166164
node = nextSibling(node)!
167165
}
168166
optimized = optimized || !!vnode.dynamicChildren

packages/runtime-core/src/renderer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export interface Renderer<HostElement = RendererElement> {
107107

108108
export interface HydrationRenderer extends Renderer<Element | ShadowRoot> {
109109
hydrate: RootHydrateFunction
110-
hydrateNode: ReturnType<typeof createHydrationFunctions>[1] | undefined
110+
hydrateNode: ReturnType<typeof createHydrationFunctions>[1]
111111
}
112112

113113
export type ElementNamespace = 'svg' | 'mathml' | undefined

packages/runtime-vapor/src/apiCreateFor.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ import { renderEffect } from './renderEffect'
3030
import { VaporVForFlags } from '../../shared/src/vaporFlags'
3131
import {
3232
currentHydrationNode,
33-
findVaporFragmentAnchor,
3433
isHydrating,
3534
locateHydrationNode,
35+
locateVaporFragmentAnchor,
3636
} from './dom/hydration'
3737
import {
3838
insertionAnchor,
@@ -97,13 +97,13 @@ export const createFor = (
9797
let parent: ParentNode | undefined | null
9898
let parentAnchor: Node
9999
if (isHydrating) {
100-
parentAnchor = findVaporFragmentAnchor(
100+
parentAnchor = locateVaporFragmentAnchor(
101101
currentHydrationNode!,
102102
FOR_ANCHOR_LABEL,
103103
)!
104104
if (__DEV__ && !parentAnchor) {
105-
// TODO warn, should not happen
106-
warn(`createFor anchor not found...`)
105+
// this should not happen
106+
throw new Error(`v-for fragment anchor node was not found.`)
107107
}
108108
} else {
109109
parentAnchor = __DEV__ ? createComment('for') : createTextNode()

packages/runtime-vapor/src/block.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ import { createComment, createTextNode } from './dom/node'
99
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
1010
import {
1111
currentHydrationNode,
12-
findVaporFragmentAnchor,
1312
isComment,
1413
isHydrating,
1514
locateHydrationNode,
15+
locateVaporFragmentAnchor,
1616
} from './dom/hydration'
17-
import { warn } from '@vue/runtime-dom'
1817

1918
export type Block =
2019
| Node
@@ -89,17 +88,17 @@ export class DynamicFragment extends VaporFragment {
8988
}
9089

9190
hydrate(label: string): void {
92-
// for `v-if="false"` the node will be an empty comment node use it as the anchor.
91+
// for `v-if="false"` the node will be an empty comment, use it as the anchor.
9392
// otherwise, find next sibling vapor fragment anchor
9493
if (isComment(currentHydrationNode!, '')) {
9594
this.anchor = currentHydrationNode
9695
} else {
97-
const anchor = findVaporFragmentAnchor(currentHydrationNode!, label)!
96+
const anchor = locateVaporFragmentAnchor(currentHydrationNode!, label)!
9897
if (anchor) {
9998
this.anchor = anchor
10099
} else if (__DEV__) {
101-
// TODO warning, should not happen
102-
warn(`DynamicFragment anchor not found...`)
100+
// this should not happen
101+
throw new Error(`${label} fragment anchor node was not found.`)
103102
}
104103
}
105104
}

packages/runtime-vapor/src/dom/hydration.ts

+24-24
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import {
66
setInsertionState,
77
} from '../insertionState'
88
import {
9-
_child,
109
disableHydrationNodeLookup,
1110
enableHydrationNodeLookup,
1211
next,
1312
} from './node'
14-
import { isDynamicAnchor, isVaporFragmentEndAnchor } from '@vue/shared'
13+
import { isVaporAnchors, isVaporFragmentAnchor } from '@vue/shared'
1514

1615
export let isHydrating = false
1716
export let currentHydrationNode: Node | null = null
@@ -33,7 +32,6 @@ function performHydration<T>(
3332

3433
// optimize anchor cache lookup
3534
;(Comment.prototype as any).$fs = undefined
36-
;(Node.prototype as any).$nc = undefined
3735
isOptimized = true
3836
}
3937
enableHydrationNodeLookup()
@@ -101,24 +99,29 @@ function adoptTemplateImpl(node: Node, template: string): Node | null {
10199
return node
102100
}
103101

102+
const hydrationPositionMap = new WeakMap<ParentNode, Node>()
103+
104104
function locateHydrationNodeImpl(hasFragmentAnchor?: boolean) {
105105
let node: Node | null
106106
// prepend / firstChild
107107
if (insertionAnchor === 0) {
108-
node = _child(insertionParent!)
108+
node = insertionParent!.firstChild
109109
} else if (insertionAnchor) {
110-
// for dynamic children, use insertionAnchor as the node
110+
// `insertionAnchor` is a Node, it is the DOM node to hydrate
111+
// Template: `...<span/><!----><span/>...`// `insertionAnchor` is the placeholder
112+
// SSR Output: `...<span/>Content<span/>...`// `insertionAnchor` is the actual node
111113
node = insertionAnchor
112114
} else {
113115
node = insertionParent
114-
? insertionParent.$nc || insertionParent.lastChild
116+
? hydrationPositionMap.get(insertionParent) || insertionParent.lastChild
115117
: currentHydrationNode
116118

117-
// if the last child is a vapor fragment end anchor, find the previous one
118-
if (hasFragmentAnchor && node && isVaporFragmentEndAnchor(node)) {
119+
// if node is a vapor fragment anchor, find the previous one
120+
if (hasFragmentAnchor && node && isVaporFragmentAnchor(node)) {
119121
node = node.previousSibling
120122
if (__DEV__ && !node) {
121-
// TODO warning, should not happen
123+
// this should not happen
124+
throw new Error(`vapor fragment anchor previous node was not found.`)
122125
}
123126
}
124127

@@ -153,7 +156,8 @@ function locateHydrationNodeImpl(hasFragmentAnchor?: boolean) {
153156
}
154157

155158
if (insertionParent && node) {
156-
insertionParent.$nc = node!.previousSibling
159+
const prev = node.previousSibling
160+
if (prev) hydrationPositionMap.set(insertionParent, prev)
157161
}
158162
}
159163

@@ -166,10 +170,6 @@ function locateHydrationNodeImpl(hasFragmentAnchor?: boolean) {
166170
currentHydrationNode = node
167171
}
168172

169-
export function isEmptyText(node: Node): node is Text {
170-
return node.nodeType === 3 && !(node as Text).data.trim()
171-
}
172-
173173
export function locateEndAnchor(
174174
node: Node | null,
175175
open = '[',
@@ -194,26 +194,26 @@ export function locateEndAnchor(
194194

195195
export function isNonHydrationNode(node: Node): boolean {
196196
return (
197-
// empty text nodes
198-
isEmptyText(node) ||
199-
// dynamic node anchors (<!--[[-->, <!--]]-->)
200-
isDynamicAnchor(node) ||
201-
// fragment end anchor (`<!--]-->`)
197+
// empty text node
198+
isEmptyTextNode(node) ||
199+
// vdom fragment end anchor (`<!--]-->`)
202200
isComment(node, ']') ||
203-
// vapor fragment end anchors
204-
isVaporFragmentEndAnchor(node)
201+
// vapor mode specific anchors
202+
isVaporAnchors(node)
205203
)
206204
}
207205

208-
export function findVaporFragmentAnchor(
206+
export function locateVaporFragmentAnchor(
209207
node: Node,
210208
anchorLabel: string,
211-
): Comment | null {
209+
): Comment | undefined {
212210
let n = node.nextSibling
213211
while (n) {
214212
if (isComment(n, anchorLabel)) return n
215213
n = n.nextSibling
216214
}
215+
}
217216

218-
return null
217+
export function isEmptyTextNode(node: Node): node is Text {
218+
return node.nodeType === 3 && !(node as Text).data.trim()
219219
}

0 commit comments

Comments
 (0)