Skip to content

Commit 18970f2

Browse files
committed
wip: vdom interop
1 parent d281d62 commit 18970f2

File tree

7 files changed

+80
-59
lines changed

7 files changed

+80
-59
lines changed

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import type { NormalizedPropsOptions } from './componentProps'
3333
import type { ObjectEmitsOptions } from './componentEmits'
3434
import { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
3535
import type { DefineComponent } from './apiDefineComponent'
36-
import type { createHydrationFunctions } from './hydration'
3736

3837
export interface App<HostElement = any> {
3938
version: string
@@ -105,7 +104,6 @@ export interface App<HostElement = any> {
105104
_container: HostElement | null
106105
_context: AppContext
107106
_instance: GenericComponentInstance | null
108-
_ssr?: boolean
109107

110108
/**
111109
* @internal custom element vnode
@@ -206,7 +204,6 @@ export interface VaporInteropInterface {
206204
parentComponent: any, // VaporComponentInstance
207205
fallback?: any, // VaporSlot
208206
) => any
209-
vdomHydrate: ReturnType<typeof createHydrationFunctions>[1] | undefined
210207
}
211208

212209
/**

packages/runtime-dom/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ export const createApp = ((...args) => {
149149

150150
export const createSSRApp = ((...args) => {
151151
const app = ensureHydrationRenderer().createApp(...args)
152-
app._ssr = true
153152

154153
if (__DEV__) {
155154
injectNativeTagCheck(app)

packages/runtime-vapor/__tests__/hydration.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3838,7 +3838,7 @@ describe('Vapor Mode hydration', () => {
38383838
})
38393839

38403840
describe('VDOM hydration interop', () => {
3841-
test('basic component', async () => {
3841+
test('basic vapor component', async () => {
38423842
const data = ref(true)
38433843
const { container } = await testHydration(
38443844
`<script setup>const data = _data; const components = _components;</script>
@@ -3891,7 +3891,7 @@ describe('VDOM hydration interop', () => {
38913891
expect(container.innerHTML).toMatchInlineSnapshot(`"false"`)
38923892
})
38933893

3894-
test.todo('slots', async () => {
3894+
test('vapor slot render vdom component', async () => {
38953895
const data = ref(true)
38963896
const { container } = await testHydration(
38973897
`<script setup>const data = _data; const components = _components;</script>

packages/runtime-vapor/src/block.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ export function insert(
154154
} else {
155155
// fragment
156156
if (block.insert) {
157-
// TODO handle hydration for vdom interop
158157
block.insert(parent, anchor)
159158
} else {
160159
insert(block.nodes, parent, anchor)

packages/runtime-vapor/src/component.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,7 @@ import {
5858
getSlot,
5959
} from './componentSlots'
6060
import { hmrReload, hmrRerender } from './hmr'
61-
import {
62-
currentHydrationNode,
63-
isHydrating,
64-
locateHydrationNode,
65-
} from './dom/hydration'
61+
import { isHydrating, locateHydrationNode } from './dom/hydration'
6662
import {
6763
insertionAnchor,
6864
insertionParent,
@@ -156,22 +152,15 @@ export function createComponent(
156152

157153
// vdom interop enabled and component is not an explicit vapor component
158154
if (appContext.vapor && !component.__vapor) {
159-
const [frag, vnode] = appContext.vapor.vdomMount(
155+
const frag = appContext.vapor.vdomMount(
160156
component as any,
161157
rawProps,
162158
rawSlots,
163159
)
164-
if (!isHydrating && _insertionParent) {
160+
161+
// `frag.insert` handles both hydration and mounting
162+
if (_insertionParent) {
165163
insert(frag, _insertionParent, _insertionAnchor)
166-
} else if (isHydrating) {
167-
appContext.vapor.vdomHydrate!(
168-
currentHydrationNode!,
169-
vnode,
170-
currentInstance as any,
171-
null,
172-
null,
173-
false,
174-
)
175164
}
176165
return frag
177166
}

packages/runtime-vapor/src/componentSlots.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ export function createSlot(
114114
: EMPTY_OBJ
115115

116116
let fragment: DynamicFragment
117-
118117
if (isRef(rawSlots._)) {
119118
fragment = instance.appContext.vapor!.vdomSlot(
120119
rawSlots._,
@@ -157,7 +156,12 @@ export function createSlot(
157156
}
158157
}
159158

160-
if (!isHydrating && _insertionParent) {
159+
if (
160+
_insertionParent &&
161+
(!isHydrating ||
162+
// for vdom interop fragment, `fragment.insert` handles both hydration and mounting
163+
fragment.insert)
164+
) {
161165
insert(fragment, _insertionParent, _insertionAnchor)
162166
}
163167

packages/runtime-vapor/src/vdomInterop.ts

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@ import type { RawSlots, VaporSlot } from './componentSlots'
3535
import { renderEffect } from './renderEffect'
3636
import { createTextNode } from './dom/node'
3737
import { optimizePropertyLookup } from './dom/prop'
38-
import { hydrateNode as vaporHydrateNode } from './dom/hydration'
38+
import {
39+
currentHydrationNode,
40+
isHydrating,
41+
locateHydrationNode,
42+
hydrateNode as vaporHydrateNode,
43+
} from './dom/hydration'
3944

4045
// mounting vapor components and slots in vdom
4146
const vaporInteropImpl: Omit<
4247
VaporInteropInterface,
43-
'vdomMount' | 'vdomUnmount' | 'vdomSlot' | 'vdomHydrate'
48+
'vdomMount' | 'vdomUnmount' | 'vdomSlot'
4449
> = {
4550
mount(vnode, container, anchor, parentComponent) {
4651
const selfAnchor = (vnode.el = vnode.anchor = createTextNode())
@@ -144,6 +149,8 @@ const vaporSlotsProxyHandler: ProxyHandler<any> = {
144149
},
145150
}
146151

152+
let vdomHydrateNode: HydrationRenderer['hydrateNode'] | undefined
153+
147154
/**
148155
* Mount vdom component in vapor
149156
*/
@@ -152,7 +159,7 @@ function createVDOMComponent(
152159
component: ConcreteComponent,
153160
rawProps?: LooseRawProps | null,
154161
rawSlots?: LooseRawSlots | null,
155-
): [VaporFragment, VNode] {
162+
): VaporFragment {
156163
const frag = new VaporFragment([])
157164
const vnode = createVNode(
158165
component,
@@ -181,16 +188,30 @@ function createVDOMComponent(
181188
}
182189

183190
frag.insert = (parentNode, anchor) => {
184-
if (!isMounted) {
185-
internals.mt(
186-
vnode,
187-
parentNode,
188-
anchor,
189-
parentInstance as any,
190-
null,
191-
undefined,
192-
false,
193-
)
191+
if (!isMounted || isHydrating) {
192+
if (isHydrating) {
193+
;(
194+
vdomHydrateNode ||
195+
(vdomHydrateNode = ensureHydrationRenderer().hydrateNode!)
196+
)(
197+
currentHydrationNode!,
198+
vnode,
199+
parentInstance as any,
200+
null,
201+
null,
202+
false,
203+
)
204+
} else {
205+
internals.mt(
206+
vnode,
207+
parentNode,
208+
anchor,
209+
parentInstance as any,
210+
null,
211+
undefined,
212+
false,
213+
)
214+
}
194215
onScopeDispose(unmount, true)
195216
isMounted = true
196217
} else {
@@ -207,7 +228,7 @@ function createVDOMComponent(
207228

208229
frag.remove = unmount
209230

210-
return [frag, vnode]
231+
return frag
211232
}
212233

213234
/**
@@ -235,28 +256,43 @@ function renderVDOMSlot(
235256
isFunction(name) ? name() : name,
236257
props,
237258
)
238-
if ((vnode.children as any[]).length) {
239-
if (fallbackNodes) {
240-
remove(fallbackNodes, parentNode)
241-
fallbackNodes = undefined
242-
}
243-
internals.p(
244-
oldVNode,
259+
if (isHydrating) {
260+
locateHydrationNode(true)
261+
;(
262+
vdomHydrateNode ||
263+
(vdomHydrateNode = ensureHydrationRenderer().hydrateNode!)
264+
)(
265+
currentHydrationNode!,
245266
vnode,
246-
parentNode,
247-
anchor,
248267
parentComponent as any,
268+
null,
269+
null,
270+
false,
249271
)
250-
oldVNode = vnode
251272
} else {
252-
if (fallback && !fallbackNodes) {
253-
// mount fallback
254-
if (oldVNode) {
255-
internals.um(oldVNode, parentComponent as any, null, true)
273+
if ((vnode.children as any[]).length) {
274+
if (fallbackNodes) {
275+
remove(fallbackNodes, parentNode)
276+
fallbackNodes = undefined
277+
}
278+
internals.p(
279+
oldVNode,
280+
vnode,
281+
parentNode,
282+
anchor,
283+
parentComponent as any,
284+
)
285+
oldVNode = vnode
286+
} else {
287+
if (fallback && !fallbackNodes) {
288+
// mount fallback
289+
if (oldVNode) {
290+
internals.um(oldVNode, parentComponent as any, null, true)
291+
}
292+
insert((fallbackNodes = fallback(props)), parentNode, anchor)
256293
}
257-
insert((fallbackNodes = fallback(props)), parentNode, anchor)
294+
oldVNode = null
258295
}
259-
oldVNode = null
260296
}
261297
})
262298
isMounted = true
@@ -284,14 +320,11 @@ function renderVDOMSlot(
284320
}
285321

286322
export const vaporInteropPlugin: Plugin = app => {
287-
const { internals, hydrateNode } = (
288-
app._ssr ? ensureHydrationRenderer() : ensureRenderer()
289-
) as HydrationRenderer
323+
const internals = ensureRenderer().internals
290324
app._context.vapor = extend(vaporInteropImpl, {
291325
vdomMount: createVDOMComponent.bind(null, internals),
292326
vdomUnmount: internals.umt,
293327
vdomSlot: renderVDOMSlot.bind(null, internals),
294-
vdomHydrate: hydrateNode,
295328
})
296329
const mount = app.mount
297330
app.mount = ((...args) => {

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