wip(vapor): more hydration

This commit is contained in:
Evan You 2025-03-07 19:45:46 +08:00
parent 64270ae1b4
commit e9d912a188
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
5 changed files with 2333 additions and 7 deletions

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ import {
import type { RawProps } from './componentProps' import type { RawProps } from './componentProps'
import { getGlobalThis } from '@vue/shared' import { getGlobalThis } from '@vue/shared'
import { optimizePropertyLookup } from './dom/prop' import { optimizePropertyLookup } from './dom/prop'
import { withHydration } from './dom/hydrate' import { withHydration } from './dom/hydration'
let _createApp: CreateAppFunction<ParentNode, VaporComponent> let _createApp: CreateAppFunction<ParentNode, VaporComponent>

View File

@ -7,7 +7,7 @@ import {
} from './component' } from './component'
import { createComment, createTextNode } from './dom/node' import { createComment, createTextNode } from './dom/node'
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity' import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
import { isHydrating } from './dom/hydrate' import { isHydrating } from './dom/hydration'
export type Block = export type Block =
| Node | Node

View File

@ -7,8 +7,16 @@ export function setCurrentHydrationNode(node: Node | null): void {
currentHydrationNode = node currentHydrationNode = node
} }
let isOptimized = false
export function withHydration(container: ParentNode, fn: () => void): void { export function withHydration(container: ParentNode, fn: () => void): void {
adoptHydrationNode = adoptHydrationNodeImpl adoptHydrationNode = adoptHydrationNodeImpl
if (!isOptimized) {
// optimize anchor cache lookup
const proto = Comment.prototype as any
proto.$p = proto.$e = undefined
isOptimized = true
}
isHydrating = true isHydrating = true
currentHydrationNode = child(container) currentHydrationNode = child(container)
const res = fn() const res = fn()
@ -48,7 +56,9 @@ function adoptHydrationNodeImpl(
let end: Node | undefined | null let end: Node | undefined | null
if (template) { if (template) {
while (node.nodeType === 8) node = next(node) if (template[0] !== '<' && template[1] !== '!') {
while (node.nodeType === 8) node = next(node)
}
adopted = end = node adopted = end = node
} else if (isComment(node, '[')) { } else if (isComment(node, '[')) {
// fragment // fragment
@ -96,14 +106,16 @@ function adoptHydrationNodeImpl(
if (__DEV__ && template) { if (__DEV__ && template) {
const type = adopted.nodeType const type = adopted.nodeType
if ( if (
type === 8 || (type === 8 && !template.startsWith('<!')) ||
(type === 1 && (type === 1 &&
!template.startsWith( !template.startsWith(
`<` + (adopted as Element).tagName.toLowerCase(), `<` + (adopted as Element).tagName.toLowerCase(),
)) || )) ||
(type === 3 && !template.startsWith((adopted as Text).data)) (type === 3 &&
template.trim() &&
!template.startsWith((adopted as Text).data))
) { ) {
// TODO recover // TODO recover and provide more info
throw new Error('hydration mismatch!') throw new Error('hydration mismatch!')
} }
} }

View File

@ -2,7 +2,7 @@ import {
adoptHydrationNode, adoptHydrationNode,
currentHydrationNode, currentHydrationNode,
isHydrating, isHydrating,
} from './hydrate' } from './hydration'
import { child } from './node' import { child } from './node'
let t: HTMLTemplateElement let t: HTMLTemplateElement