Skip to content

Commit 0cf3a63

Browse files
committed
refactor: add preHydration and postHydration functions for node handling
1 parent 1248172 commit 0cf3a63

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

packages/runtime-core/src/hydration.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ const getContainerType = (
8484
return undefined
8585
}
8686

87+
export function isDynamicAnchor(node: Node): boolean {
88+
return isComment(node) && (node.data === '[[' || node.data === ']]')
89+
}
90+
8791
export const isComment = (node: Node): node is Comment =>
8892
node.nodeType === DOMNodeTypes.COMMENT
8993

@@ -119,10 +123,6 @@ export function createHydrationFunctions(
119123
},
120124
} = rendererInternals
121125

122-
function isDynamicAnchor(node: Node): boolean {
123-
return isComment(node) && (node.data === '[[' || node.data === ']]')
124-
}
125-
126126
function nextSibling(node: Node) {
127127
let n = next(node)
128128
// skip dynamic child anchor

packages/runtime-core/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,3 +557,7 @@ export { startMeasure, endMeasure } from './profiling'
557557
* @internal
558558
*/
559559
export { initFeatureFlags } from './featureFlags'
560+
/**
561+
* @internal
562+
*/
563+
export { isDynamicAnchor } from './hydration'

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
resetInsertionState,
77
setInsertionState,
88
} from '../insertionState'
9-
import { child, next } from './node'
9+
import { child, next, postHydration, preHydration } from './node'
1010

1111
export let isHydrating = false
1212
export let currentHydrationNode: Node | null = null
@@ -25,12 +25,14 @@ export function withHydration(container: ParentNode, fn: () => void): void {
2525
;(Comment.prototype as any).$fs = undefined
2626
isOptimized = true
2727
}
28+
preHydration()
2829
isHydrating = true
2930
setInsertionState(container, 0)
3031
const res = fn()
3132
resetInsertionState()
3233
currentHydrationNode = null
3334
isHydrating = false
35+
postHydration()
3436
return res
3537
}
3638

@@ -120,10 +122,6 @@ function locateHydrationNodeImpl() {
120122
currentHydrationNode = node
121123
}
122124

123-
export function isDynamicAnchor(node: Node): node is Comment {
124-
return isComment(node, '[[') || isComment(node, ']]')
125-
}
126-
127125
export function isEmptyText(node: Node): node is Text {
128126
return node.nodeType === 3 && !(node as Text).data.trim()
129127
}

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

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import {
2-
isComment,
3-
isDynamicAnchor,
4-
isEmptyText,
5-
isHydrating,
6-
locateEndAnchor,
7-
} from './hydration'
1+
import { isDynamicAnchor } from '@vue/runtime-dom'
2+
import { isComment, isEmptyText, locateEndAnchor } from './hydration'
83

94
/*! #__NO_SIDE_EFFECTS__ */
105
export function createTextNode(value = ''): Text {
@@ -27,9 +22,12 @@ export function child(node: ParentNode): Node {
2722
}
2823

2924
/*! #__NO_SIDE_EFFECTS__ */
30-
export function nthChild(node: Node, i: number): Node {
31-
if (!isHydrating) return node.childNodes[i]
25+
export function _nthChild(node: Node, i: number): Node {
26+
return node.childNodes[i]
27+
}
3228

29+
/*! #__NO_SIDE_EFFECTS__ */
30+
export function __nthChild(node: Node, i: number): Node {
3331
let n = node.firstChild!
3432
for (let start = 0; start < i; start++) {
3533
n = next(n) as ChildNode
@@ -38,9 +36,12 @@ export function nthChild(node: Node, i: number): Node {
3836
}
3937

4038
/*! #__NO_SIDE_EFFECTS__ */
41-
export function next(node: Node): Node {
42-
if (!isHydrating) return node.nextSibling!
39+
function _next(node: Node): Node {
40+
return node.nextSibling!
41+
}
4342

43+
/*! #__NO_SIDE_EFFECTS__ */
44+
function __next(node: Node): Node {
4445
// process fragment as a single node
4546
if (node && isComment(node, '[')) {
4647
node = locateEndAnchor(node)!
@@ -53,3 +54,46 @@ export function next(node: Node): Node {
5354
}
5455
return n
5556
}
57+
58+
type NextFn = (node: Node) => Node
59+
type NthChildFn = (node: Node, i: number) => Node
60+
61+
interface DelegatedNextFunction extends NextFn {
62+
impl: NextFn
63+
}
64+
interface DelegatedNthChildFunction extends NthChildFn {
65+
impl: NthChildFn
66+
}
67+
68+
/*! #__NO_SIDE_EFFECTS__ */
69+
export const next: DelegatedNextFunction = node => {
70+
return next.impl(node)
71+
}
72+
next.impl = _next
73+
74+
/*! #__NO_SIDE_EFFECTS__ */
75+
export const nthChild: DelegatedNthChildFunction = (node, i) => {
76+
return nthChild.impl(node, i)
77+
}
78+
nthChild.impl = _nthChild
79+
80+
// During hydration, there might be differences between the server-rendered (SSR)
81+
// HTML and the client-side template.
82+
// For example, a dynamic node `<!>` in the template might be rendered as a
83+
// Fragment (`<!--[-->...<!--]-->`) in the SSR output.
84+
// The content of the Fragment affects the lookup results of the `next` and
85+
// `nthChild` functions.
86+
// To ensure the hydration process correctly finds nodes, we need to treat the
87+
// Fragment as a single node.
88+
// Therefore, during hydration, we need to temporarily switch the implementations
89+
// of `next` and `nthChild`. After hydration is complete, their implementations
90+
// are restored to the original versions.
91+
export function preHydration(): void {
92+
next.impl = __next
93+
nthChild.impl = __nthChild
94+
}
95+
96+
export function postHydration(): void {
97+
next.impl = _next
98+
nthChild.impl = _nthChild
99+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy