types: cleanup renderer & hydration typing
This commit is contained in:
parent
629ee75588
commit
80904e92b8
@ -14,6 +14,11 @@ import { warn } from './warning'
|
||||
import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
|
||||
import { RendererOptions } from './renderer'
|
||||
|
||||
export type RootHydrateFunction = (
|
||||
vnode: VNode<Node, Element>,
|
||||
container: Element
|
||||
) => void
|
||||
|
||||
// Note: hydration is DOM-specific
|
||||
// But we have to place it in core due to tight coupling with core - splitting
|
||||
// it out creates a ton of unnecessary complexity.
|
||||
@ -23,7 +28,7 @@ export function createHydrationFunctions(
|
||||
mountComponent: any, // TODO
|
||||
patchProp: RendererOptions['patchProp']
|
||||
) {
|
||||
const hydrate = (vnode: VNode, container: Element) => {
|
||||
const hydrate: RootHydrateFunction = (vnode, container) => {
|
||||
if (__DEV__ && !container.hasChildNodes()) {
|
||||
warn(`Attempting to hydrate existing markup but container is empty.`)
|
||||
return
|
||||
|
@ -179,7 +179,13 @@ export {
|
||||
ComponentOptionsWithArrayProps
|
||||
} from './apiOptions'
|
||||
export { ComponentPublicInstance } from './componentProxy'
|
||||
export { RendererOptions, RootRenderFunction } from './renderer'
|
||||
export {
|
||||
Renderer,
|
||||
HydrationRenderer,
|
||||
RendererOptions,
|
||||
RootRenderFunction
|
||||
} from './renderer'
|
||||
export { RootHydrateFunction } from './hydration'
|
||||
export { Slot, Slots } from './componentSlots'
|
||||
export {
|
||||
Prop,
|
||||
|
@ -62,10 +62,24 @@ import {
|
||||
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
|
||||
import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
|
||||
import { registerHMR, unregisterHMR } from './hmr'
|
||||
import { createHydrationFunctions } from './hydration'
|
||||
import { createHydrationFunctions, RootHydrateFunction } from './hydration'
|
||||
|
||||
const __HMR__ = __BUNDLER__ && __DEV__
|
||||
|
||||
export interface Renderer<HostNode = any, HostElement = any> {
|
||||
render: RootRenderFunction<HostNode, HostElement>
|
||||
createApp: CreateAppFunction<HostElement>
|
||||
}
|
||||
|
||||
export interface HydrationRenderer extends Renderer<Node, Element> {
|
||||
hydrate: RootHydrateFunction
|
||||
}
|
||||
|
||||
export type RootRenderFunction<HostNode, HostElement> = (
|
||||
vnode: VNode<HostNode, HostElement> | null,
|
||||
container: HostElement
|
||||
) => void
|
||||
|
||||
export interface RendererOptions<HostNode = any, HostElement = any> {
|
||||
patchProp(
|
||||
el: HostElement,
|
||||
@ -102,41 +116,6 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
|
||||
): HostElement
|
||||
}
|
||||
|
||||
export type RootRenderFunction<HostNode, HostElement> = (
|
||||
vnode: VNode<HostNode, HostElement> | null,
|
||||
dom: HostElement
|
||||
) => void
|
||||
|
||||
// An object exposing the internals of a renderer, passed to tree-shakeable
|
||||
// features so that they can be decoupled from this file.
|
||||
export interface RendererInternals<HostNode = any, HostElement = any> {
|
||||
patch: (
|
||||
n1: VNode<HostNode, HostElement> | null, // null means this is a mount
|
||||
n2: VNode<HostNode, HostElement>,
|
||||
container: HostElement,
|
||||
anchor?: HostNode | null,
|
||||
parentComponent?: ComponentInternalInstance | null,
|
||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
|
||||
isSVG?: boolean,
|
||||
optimized?: boolean
|
||||
) => void
|
||||
unmount: (
|
||||
vnode: VNode<HostNode, HostElement>,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
||||
doRemove?: boolean
|
||||
) => void
|
||||
move: (
|
||||
vnode: VNode<HostNode, HostElement>,
|
||||
container: HostElement,
|
||||
anchor: HostNode | null,
|
||||
type: MoveType,
|
||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
|
||||
) => void
|
||||
next: (vnode: VNode<HostNode, HostElement>) => HostNode | null
|
||||
options: RendererOptions<HostNode, HostElement>
|
||||
}
|
||||
|
||||
export const enum MoveType {
|
||||
ENTER,
|
||||
LEAVE,
|
||||
@ -186,25 +165,36 @@ export function createRenderer<
|
||||
HostNode extends object = any,
|
||||
HostElement extends HostNode = any
|
||||
>(options: RendererOptions<HostNode, HostElement>) {
|
||||
const res = baseCreateRenderer(options)
|
||||
return res as typeof res & {
|
||||
hydrate: undefined
|
||||
}
|
||||
return baseCreateRenderer<HostNode, HostElement>(options)
|
||||
}
|
||||
|
||||
// Separate API for creating hydration-enabled renderer.
|
||||
// Hydration logic is only used when calling this function, making it
|
||||
// tree-shakable.
|
||||
export function createHydrationRenderer<
|
||||
HostNode extends object = any,
|
||||
HostElement extends HostNode = any
|
||||
>(options: RendererOptions<HostNode, HostElement>) {
|
||||
const res = baseCreateRenderer(options, createHydrationFunctions)
|
||||
return res as typeof res & {
|
||||
hydrate: ReturnType<typeof createHydrationFunctions>[0]
|
||||
}
|
||||
export function createHydrationRenderer(
|
||||
options: RendererOptions<Node, Element>
|
||||
) {
|
||||
return baseCreateRenderer<Node, Element>(options, createHydrationFunctions)
|
||||
}
|
||||
|
||||
// overload 1: no hydration
|
||||
function baseCreateRenderer<
|
||||
HostNode extends object = any,
|
||||
HostElement extends HostNode = any
|
||||
>(
|
||||
options: RendererOptions<HostNode, HostElement>
|
||||
): Renderer<HostNode, HostElement>
|
||||
|
||||
// overload 2: with hydration
|
||||
function baseCreateRenderer<
|
||||
HostNode extends object = any,
|
||||
HostElement extends HostNode = any
|
||||
>(
|
||||
options: RendererOptions<HostNode, HostElement>,
|
||||
createHydrationFns: typeof createHydrationFunctions
|
||||
): HydrationRenderer
|
||||
|
||||
// implementation
|
||||
function baseCreateRenderer<
|
||||
HostNode extends object = any,
|
||||
HostElement extends HostNode = any
|
||||
@ -1862,6 +1852,36 @@ function baseCreateRenderer<
|
||||
}
|
||||
}
|
||||
|
||||
// An object exposing the internals of a renderer, passed to tree-shakeable
|
||||
// features so that they can be decoupled from this file.
|
||||
export interface RendererInternals<HostNode = any, HostElement = any> {
|
||||
patch: (
|
||||
n1: VNode<HostNode, HostElement> | null, // null means this is a mount
|
||||
n2: VNode<HostNode, HostElement>,
|
||||
container: HostElement,
|
||||
anchor?: HostNode | null,
|
||||
parentComponent?: ComponentInternalInstance | null,
|
||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
|
||||
isSVG?: boolean,
|
||||
optimized?: boolean
|
||||
) => void
|
||||
unmount: (
|
||||
vnode: VNode<HostNode, HostElement>,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
||||
doRemove?: boolean
|
||||
) => void
|
||||
move: (
|
||||
vnode: VNode<HostNode, HostElement>,
|
||||
container: HostElement,
|
||||
anchor: HostNode | null,
|
||||
type: MoveType,
|
||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
|
||||
) => void
|
||||
next: (vnode: VNode<HostNode, HostElement>) => HostNode | null
|
||||
options: RendererOptions<HostNode, HostElement>
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
|
||||
function getSequence(arr: number[]): number[] {
|
||||
const p = arr.slice()
|
||||
|
@ -4,8 +4,10 @@ import {
|
||||
warn,
|
||||
RootRenderFunction,
|
||||
CreateAppFunction,
|
||||
VNode,
|
||||
App
|
||||
Renderer,
|
||||
HydrationRenderer,
|
||||
App,
|
||||
RootHydrateFunction
|
||||
} from '@vue/runtime-core'
|
||||
import { nodeOps } from './nodeOps'
|
||||
import { patchProp } from './patchProp'
|
||||
@ -19,9 +21,7 @@ const rendererOptions = {
|
||||
|
||||
// lazy create the renderer - this makes core renderer logic tree-shakable
|
||||
// in case the user only imports reactivity utilities from Vue.
|
||||
let renderer:
|
||||
| ReturnType<typeof createRenderer>
|
||||
| ReturnType<typeof createHydrationRenderer>
|
||||
let renderer: Renderer | HydrationRenderer
|
||||
|
||||
let enabledHydration = false
|
||||
|
||||
@ -34,7 +34,7 @@ function ensureHydrationRenderer() {
|
||||
? renderer
|
||||
: createHydrationRenderer(rendererOptions)
|
||||
enabledHydration = true
|
||||
return renderer as ReturnType<typeof createHydrationRenderer>
|
||||
return renderer as HydrationRenderer
|
||||
}
|
||||
|
||||
// use explicit type casts here to avoid import() calls in rolled-up d.ts
|
||||
@ -44,7 +44,7 @@ export const render = ((...args) => {
|
||||
|
||||
export const hydrate = ((...args) => {
|
||||
ensureHydrationRenderer().hydrate(...args)
|
||||
}) as (vnode: VNode, container: Element) => void
|
||||
}) as RootHydrateFunction
|
||||
|
||||
export const createApp = ((...args) => {
|
||||
const app = ensureRenderer().createApp(...args)
|
||||
|
Loading…
Reference in New Issue
Block a user