Skip to content

Commit 80904e9

Browse files
committed
types: cleanup renderer & hydration typing
1 parent 629ee75 commit 80904e9

File tree

4 files changed

+87
-56
lines changed

4 files changed

+87
-56
lines changed

packages/runtime-core/src/hydration.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import { warn } from './warning'
1414
import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
1515
import { RendererOptions } from './renderer'
1616

17+
export type RootHydrateFunction = (
18+
vnode: VNode<Node, Element>,
19+
container: Element
20+
) => void
21+
1722
// Note: hydration is DOM-specific
1823
// But we have to place it in core due to tight coupling with core - splitting
1924
// it out creates a ton of unnecessary complexity.
@@ -23,7 +28,7 @@ export function createHydrationFunctions(
2328
mountComponent: any, // TODO
2429
patchProp: RendererOptions['patchProp']
2530
) {
26-
const hydrate = (vnode: VNode, container: Element) => {
31+
const hydrate: RootHydrateFunction = (vnode, container) => {
2732
if (__DEV__ && !container.hasChildNodes()) {
2833
warn(`Attempting to hydrate existing markup but container is empty.`)
2934
return

packages/runtime-core/src/index.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,13 @@ export {
179179
ComponentOptionsWithArrayProps
180180
} from './apiOptions'
181181
export { ComponentPublicInstance } from './componentProxy'
182-
export { RendererOptions, RootRenderFunction } from './renderer'
182+
export {
183+
Renderer,
184+
HydrationRenderer,
185+
RendererOptions,
186+
RootRenderFunction
187+
} from './renderer'
188+
export { RootHydrateFunction } from './hydration'
183189
export { Slot, Slots } from './componentSlots'
184190
export {
185191
Prop,

packages/runtime-core/src/renderer.ts

+67-47
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,24 @@ import {
6262
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
6363
import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
6464
import { registerHMR, unregisterHMR } from './hmr'
65-
import { createHydrationFunctions } from './hydration'
65+
import { createHydrationFunctions, RootHydrateFunction } from './hydration'
6666

6767
const __HMR__ = __BUNDLER__ && __DEV__
6868

69+
export interface Renderer<HostNode = any, HostElement = any> {
70+
render: RootRenderFunction<HostNode, HostElement>
71+
createApp: CreateAppFunction<HostElement>
72+
}
73+
74+
export interface HydrationRenderer extends Renderer<Node, Element> {
75+
hydrate: RootHydrateFunction
76+
}
77+
78+
export type RootRenderFunction<HostNode, HostElement> = (
79+
vnode: VNode<HostNode, HostElement> | null,
80+
container: HostElement
81+
) => void
82+
6983
export interface RendererOptions<HostNode = any, HostElement = any> {
7084
patchProp(
7185
el: HostElement,
@@ -102,41 +116,6 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
102116
): HostElement
103117
}
104118

105-
export type RootRenderFunction<HostNode, HostElement> = (
106-
vnode: VNode<HostNode, HostElement> | null,
107-
dom: HostElement
108-
) => void
109-
110-
// An object exposing the internals of a renderer, passed to tree-shakeable
111-
// features so that they can be decoupled from this file.
112-
export interface RendererInternals<HostNode = any, HostElement = any> {
113-
patch: (
114-
n1: VNode<HostNode, HostElement> | null, // null means this is a mount
115-
n2: VNode<HostNode, HostElement>,
116-
container: HostElement,
117-
anchor?: HostNode | null,
118-
parentComponent?: ComponentInternalInstance | null,
119-
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
120-
isSVG?: boolean,
121-
optimized?: boolean
122-
) => void
123-
unmount: (
124-
vnode: VNode<HostNode, HostElement>,
125-
parentComponent: ComponentInternalInstance | null,
126-
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
127-
doRemove?: boolean
128-
) => void
129-
move: (
130-
vnode: VNode<HostNode, HostElement>,
131-
container: HostElement,
132-
anchor: HostNode | null,
133-
type: MoveType,
134-
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
135-
) => void
136-
next: (vnode: VNode<HostNode, HostElement>) => HostNode | null
137-
options: RendererOptions<HostNode, HostElement>
138-
}
139-
140119
export const enum MoveType {
141120
ENTER,
142121
LEAVE,
@@ -186,25 +165,36 @@ export function createRenderer<
186165
HostNode extends object = any,
187166
HostElement extends HostNode = any
188167
>(options: RendererOptions<HostNode, HostElement>) {
189-
const res = baseCreateRenderer(options)
190-
return res as typeof res & {
191-
hydrate: undefined
192-
}
168+
return baseCreateRenderer<HostNode, HostElement>(options)
193169
}
194170

195171
// Separate API for creating hydration-enabled renderer.
196172
// Hydration logic is only used when calling this function, making it
197173
// tree-shakable.
198-
export function createHydrationRenderer<
174+
export function createHydrationRenderer(
175+
options: RendererOptions<Node, Element>
176+
) {
177+
return baseCreateRenderer<Node, Element>(options, createHydrationFunctions)
178+
}
179+
180+
// overload 1: no hydration
181+
function baseCreateRenderer<
199182
HostNode extends object = any,
200183
HostElement extends HostNode = any
201-
>(options: RendererOptions<HostNode, HostElement>) {
202-
const res = baseCreateRenderer(options, createHydrationFunctions)
203-
return res as typeof res & {
204-
hydrate: ReturnType<typeof createHydrationFunctions>[0]
205-
}
206-
}
184+
>(
185+
options: RendererOptions<HostNode, HostElement>
186+
): Renderer<HostNode, HostElement>
187+
188+
// overload 2: with hydration
189+
function baseCreateRenderer<
190+
HostNode extends object = any,
191+
HostElement extends HostNode = any
192+
>(
193+
options: RendererOptions<HostNode, HostElement>,
194+
createHydrationFns: typeof createHydrationFunctions
195+
): HydrationRenderer
207196

197+
// implementation
208198
function baseCreateRenderer<
209199
HostNode extends object = any,
210200
HostElement extends HostNode = any
@@ -1862,6 +1852,36 @@ function baseCreateRenderer<
18621852
}
18631853
}
18641854

1855+
// An object exposing the internals of a renderer, passed to tree-shakeable
1856+
// features so that they can be decoupled from this file.
1857+
export interface RendererInternals<HostNode = any, HostElement = any> {
1858+
patch: (
1859+
n1: VNode<HostNode, HostElement> | null, // null means this is a mount
1860+
n2: VNode<HostNode, HostElement>,
1861+
container: HostElement,
1862+
anchor?: HostNode | null,
1863+
parentComponent?: ComponentInternalInstance | null,
1864+
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
1865+
isSVG?: boolean,
1866+
optimized?: boolean
1867+
) => void
1868+
unmount: (
1869+
vnode: VNode<HostNode, HostElement>,
1870+
parentComponent: ComponentInternalInstance | null,
1871+
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
1872+
doRemove?: boolean
1873+
) => void
1874+
move: (
1875+
vnode: VNode<HostNode, HostElement>,
1876+
container: HostElement,
1877+
anchor: HostNode | null,
1878+
type: MoveType,
1879+
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
1880+
) => void
1881+
next: (vnode: VNode<HostNode, HostElement>) => HostNode | null
1882+
options: RendererOptions<HostNode, HostElement>
1883+
}
1884+
18651885
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
18661886
function getSequence(arr: number[]): number[] {
18671887
const p = arr.slice()

packages/runtime-dom/src/index.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import {
44
warn,
55
RootRenderFunction,
66
CreateAppFunction,
7-
VNode,
8-
App
7+
Renderer,
8+
HydrationRenderer,
9+
App,
10+
RootHydrateFunction
911
} from '@vue/runtime-core'
1012
import { nodeOps } from './nodeOps'
1113
import { patchProp } from './patchProp'
@@ -19,9 +21,7 @@ const rendererOptions = {
1921

2022
// lazy create the renderer - this makes core renderer logic tree-shakable
2123
// in case the user only imports reactivity utilities from Vue.
22-
let renderer:
23-
| ReturnType<typeof createRenderer>
24-
| ReturnType<typeof createHydrationRenderer>
24+
let renderer: Renderer | HydrationRenderer
2525

2626
let enabledHydration = false
2727

@@ -34,7 +34,7 @@ function ensureHydrationRenderer() {
3434
? renderer
3535
: createHydrationRenderer(rendererOptions)
3636
enabledHydration = true
37-
return renderer as ReturnType<typeof createHydrationRenderer>
37+
return renderer as HydrationRenderer
3838
}
3939

4040
// use explicit type casts here to avoid import() calls in rolled-up d.ts
@@ -44,7 +44,7 @@ export const render = ((...args) => {
4444

4545
export const hydrate = ((...args) => {
4646
ensureHydrationRenderer().hydrate(...args)
47-
}) as (vnode: VNode, container: Element) => void
47+
}) as RootHydrateFunction
4848

4949
export const createApp = ((...args) => {
5050
const app = ensureRenderer().createApp(...args)

0 commit comments

Comments
 (0)