perf: prevent renderer hot functions being inlined by minifiers
Terser will aggressively inline hot functions in renderer.ts in order to reduce "function" declarations, but the inlining leads to performance overhead (small, but noticeable in benchmarks). Since we cannot control user's minifier options, we have to avoid the deopt in the source code by using arrow functions in hot paths.
This commit is contained in:
parent
f71a50ae96
commit
629ee75588
@ -12,6 +12,7 @@ import { ComponentInternalInstance } from './component'
|
|||||||
import { invokeDirectiveHook } from './directives'
|
import { invokeDirectiveHook } from './directives'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
|
import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
|
||||||
|
import { RendererOptions } from './renderer'
|
||||||
|
|
||||||
// Note: hydration is DOM-specific
|
// Note: hydration is DOM-specific
|
||||||
// But we have to place it in core due to tight coupling with core - splitting
|
// But we have to place it in core due to tight coupling with core - splitting
|
||||||
@ -20,9 +21,9 @@ import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
|
|||||||
// passed in via arguments.
|
// passed in via arguments.
|
||||||
export function createHydrationFunctions(
|
export function createHydrationFunctions(
|
||||||
mountComponent: any, // TODO
|
mountComponent: any, // TODO
|
||||||
patchProp: any // TODO
|
patchProp: RendererOptions['patchProp']
|
||||||
) {
|
) {
|
||||||
function hydrate(vnode: VNode, container: Element) {
|
const hydrate = (vnode: VNode, container: Element) => {
|
||||||
if (__DEV__ && !container.hasChildNodes()) {
|
if (__DEV__ && !container.hasChildNodes()) {
|
||||||
warn(`Attempting to hydrate existing markup but container is empty.`)
|
warn(`Attempting to hydrate existing markup but container is empty.`)
|
||||||
return
|
return
|
||||||
@ -34,11 +35,11 @@ export function createHydrationFunctions(
|
|||||||
// TODO handle mismatches
|
// TODO handle mismatches
|
||||||
// TODO SVG
|
// TODO SVG
|
||||||
// TODO Suspense
|
// TODO Suspense
|
||||||
function hydrateNode(
|
const hydrateNode = (
|
||||||
node: Node,
|
node: Node,
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
parentComponent: ComponentInternalInstance | null = null
|
parentComponent: ComponentInternalInstance | null = null
|
||||||
): Node | null | undefined {
|
): Node | null | undefined => {
|
||||||
const { type, shapeFlag } = vnode
|
const { type, shapeFlag } = vnode
|
||||||
vnode.el = node
|
vnode.el = node
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -73,11 +74,11 @@ export function createHydrationFunctions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hydrateElement(
|
const hydrateElement = (
|
||||||
el: Element,
|
el: Element,
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
parentComponent: ComponentInternalInstance | null
|
parentComponent: ComponentInternalInstance | null
|
||||||
) {
|
) => {
|
||||||
const { props, patchFlag } = vnode
|
const { props, patchFlag } = vnode
|
||||||
// skip props & children if this is hoisted static nodes
|
// skip props & children if this is hoisted static nodes
|
||||||
if (patchFlag !== PatchFlags.HOISTED) {
|
if (patchFlag !== PatchFlags.HOISTED) {
|
||||||
@ -124,11 +125,11 @@ export function createHydrationFunctions(
|
|||||||
return el.nextSibling
|
return el.nextSibling
|
||||||
}
|
}
|
||||||
|
|
||||||
function hydrateChildren(
|
const hydrateChildren = (
|
||||||
node: Node | null | undefined,
|
node: Node | null | undefined,
|
||||||
vnodes: VNode[],
|
vnodes: VNode[],
|
||||||
parentComponent: ComponentInternalInstance | null
|
parentComponent: ComponentInternalInstance | null
|
||||||
): Node | null | undefined {
|
): Node | null | undefined => {
|
||||||
for (let i = 0; node != null && i < vnodes.length; i++) {
|
for (let i = 0; node != null && i < vnodes.length; i++) {
|
||||||
// TODO can skip normalizeVNode in optimized mode
|
// TODO can skip normalizeVNode in optimized mode
|
||||||
// (need hint on rendered markup?)
|
// (need hint on rendered markup?)
|
||||||
|
@ -233,21 +233,7 @@ function baseCreateRenderer<
|
|||||||
insertStaticContent: hostInsertStaticContent
|
insertStaticContent: hostInsertStaticContent
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
const internals: RendererInternals<HostNode, HostElement> = {
|
const patch = (
|
||||||
patch,
|
|
||||||
unmount,
|
|
||||||
move,
|
|
||||||
next: getNextHostNode,
|
|
||||||
options
|
|
||||||
}
|
|
||||||
|
|
||||||
let hydrate: ReturnType<typeof createHydrationFunctions>[0] | undefined
|
|
||||||
let hydrateNode: ReturnType<typeof createHydrationFunctions>[1] | undefined
|
|
||||||
if (createHydrationFns) {
|
|
||||||
;[hydrate, hydrateNode] = createHydrationFns(mountComponent, hostPatchProp)
|
|
||||||
}
|
|
||||||
|
|
||||||
function patch(
|
|
||||||
n1: HostVNode | null, // null means this is a mount
|
n1: HostVNode | null, // null means this is a mount
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -256,7 +242,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null = null,
|
parentSuspense: HostSuspenseBoundary | null = null,
|
||||||
isSVG: boolean = false,
|
isSVG: boolean = false,
|
||||||
optimized: boolean = false
|
optimized: boolean = false
|
||||||
) {
|
) => {
|
||||||
// patching & not same type, unmount old tree
|
// patching & not same type, unmount old tree
|
||||||
if (n1 != null && !isSameVNodeType(n1, n2)) {
|
if (n1 != null && !isSameVNodeType(n1, n2)) {
|
||||||
anchor = getNextHostNode(n1)
|
anchor = getNextHostNode(n1)
|
||||||
@ -342,12 +328,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processText(
|
const processText = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null
|
anchor: HostNode | null
|
||||||
) {
|
) => {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert(
|
hostInsert(
|
||||||
(n2.el = hostCreateText(n2.children as string)),
|
(n2.el = hostCreateText(n2.children as string)),
|
||||||
@ -362,12 +348,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processCommentNode(
|
const processCommentNode = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null
|
anchor: HostNode | null
|
||||||
) {
|
) => {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert(
|
hostInsert(
|
||||||
(n2.el = hostCreateComment((n2.children as string) || '')),
|
(n2.el = hostCreateComment((n2.children as string) || '')),
|
||||||
@ -380,12 +366,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountStaticNode(
|
const mountStaticNode = (
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) => {
|
||||||
if (n2.el != null && hostCloneNode !== undefined) {
|
if (n2.el != null && hostCloneNode !== undefined) {
|
||||||
hostInsert(hostCloneNode(n2.el), container, anchor)
|
hostInsert(hostCloneNode(n2.el), container, anchor)
|
||||||
} else {
|
} else {
|
||||||
@ -400,7 +386,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processElement(
|
const processElement = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -409,7 +395,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
isSVG = isSVG || (n2.type as string) === 'svg'
|
isSVG = isSVG || (n2.type as string) === 'svg'
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
mountElement(
|
mountElement(
|
||||||
@ -429,7 +415,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountElement(
|
const mountElement = (
|
||||||
vnode: HostVNode,
|
vnode: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
@ -437,7 +423,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
let el: HostElement
|
let el: HostElement
|
||||||
const { type, props, shapeFlag, transition, scopeId, patchFlag } = vnode
|
const { type, props, shapeFlag, transition, scopeId, patchFlag } = vnode
|
||||||
if (
|
if (
|
||||||
@ -509,7 +495,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountChildren(
|
const mountChildren = (
|
||||||
children: HostVNodeChildren,
|
children: HostVNodeChildren,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
@ -518,7 +504,7 @@ function baseCreateRenderer<
|
|||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean,
|
optimized: boolean,
|
||||||
start: number = 0
|
start: number = 0
|
||||||
) {
|
) => {
|
||||||
for (let i = start; i < children.length; i++) {
|
for (let i = start; i < children.length; i++) {
|
||||||
const child = (children[i] = optimized
|
const child = (children[i] = optimized
|
||||||
? cloneIfMounted(children[i] as HostVNode)
|
? cloneIfMounted(children[i] as HostVNode)
|
||||||
@ -536,14 +522,14 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchElement(
|
const patchElement = (
|
||||||
n1: HostVNode,
|
n1: HostVNode,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
const el = (n2.el = n1.el) as HostElement
|
const el = (n2.el = n1.el) as HostElement
|
||||||
let { patchFlag, dynamicChildren } = n2
|
let { patchFlag, dynamicChildren } = n2
|
||||||
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
||||||
@ -673,14 +659,14 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The fast path for blocks.
|
// The fast path for blocks.
|
||||||
function patchBlockChildren(
|
const patchBlockChildren = (
|
||||||
oldChildren: HostVNode[],
|
oldChildren: HostVNode[],
|
||||||
newChildren: HostVNode[],
|
newChildren: HostVNode[],
|
||||||
fallbackContainer: HostElement,
|
fallbackContainer: HostElement,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) => {
|
||||||
for (let i = 0; i < newChildren.length; i++) {
|
for (let i = 0; i < newChildren.length; i++) {
|
||||||
const oldVNode = oldChildren[i]
|
const oldVNode = oldChildren[i]
|
||||||
const newVNode = newChildren[i]
|
const newVNode = newChildren[i]
|
||||||
@ -711,7 +697,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchProps(
|
const patchProps = (
|
||||||
el: HostElement,
|
el: HostElement,
|
||||||
vnode: HostVNode,
|
vnode: HostVNode,
|
||||||
oldProps: Data,
|
oldProps: Data,
|
||||||
@ -719,7 +705,7 @@ function baseCreateRenderer<
|
|||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) => {
|
||||||
if (oldProps !== newProps) {
|
if (oldProps !== newProps) {
|
||||||
for (const key in newProps) {
|
for (const key in newProps) {
|
||||||
if (isReservedProp(key)) continue
|
if (isReservedProp(key)) continue
|
||||||
@ -761,7 +747,7 @@ function baseCreateRenderer<
|
|||||||
|
|
||||||
let devFragmentID = 0
|
let devFragmentID = 0
|
||||||
|
|
||||||
function processFragment(
|
const processFragment = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -770,7 +756,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
const showID = __DEV__ && !__TEST__
|
const showID = __DEV__ && !__TEST__
|
||||||
const fragmentStartAnchor = (n2.el = n1
|
const fragmentStartAnchor = (n2.el = n1
|
||||||
? n1.el
|
? n1.el
|
||||||
@ -840,7 +826,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processPortal(
|
const processPortal = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -849,7 +835,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
const targetSelector = n2.props && n2.props.target
|
const targetSelector = n2.props && n2.props.target
|
||||||
const { patchFlag, shapeFlag, children } = n2
|
const { patchFlag, shapeFlag, children } = n2
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
@ -934,7 +920,7 @@ function baseCreateRenderer<
|
|||||||
processCommentNode(n1, n2, container, anchor)
|
processCommentNode(n1, n2, container, anchor)
|
||||||
}
|
}
|
||||||
|
|
||||||
function processComponent(
|
const processComponent = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -943,7 +929,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
|
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
|
||||||
;(parentComponent!.sink as KeepAliveSink).activate(
|
;(parentComponent!.sink as KeepAliveSink).activate(
|
||||||
@ -1008,14 +994,14 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountComponent(
|
const mountComponent = (
|
||||||
initialVNode: HostVNode,
|
initialVNode: HostVNode,
|
||||||
container: HostElement | null, // only null during hydration
|
container: HostElement | null, // only null during hydration
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) => {
|
||||||
const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(
|
const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(
|
||||||
initialVNode,
|
initialVNode,
|
||||||
parentComponent
|
parentComponent
|
||||||
@ -1070,14 +1056,14 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupRenderEffect(
|
const setupRenderEffect = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
initialVNode: HostVNode,
|
initialVNode: HostVNode,
|
||||||
container: HostElement | null, // only null during hydration
|
container: HostElement | null, // only null during hydration
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) => {
|
||||||
// create reactive effect for rendering
|
// create reactive effect for rendering
|
||||||
instance.update = effect(function componentEffect() {
|
instance.update = effect(function componentEffect() {
|
||||||
if (!instance.isMounted) {
|
if (!instance.isMounted) {
|
||||||
@ -1168,10 +1154,10 @@ function baseCreateRenderer<
|
|||||||
}, __DEV__ ? createDevEffectOptions(instance) : prodEffectOptions)
|
}, __DEV__ ? createDevEffectOptions(instance) : prodEffectOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateComponentPreRender(
|
const updateComponentPreRender = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
nextVNode: HostVNode
|
nextVNode: HostVNode
|
||||||
) {
|
) => {
|
||||||
nextVNode.component = instance
|
nextVNode.component = instance
|
||||||
instance.vnode = nextVNode
|
instance.vnode = nextVNode
|
||||||
instance.next = null
|
instance.next = null
|
||||||
@ -1179,7 +1165,7 @@ function baseCreateRenderer<
|
|||||||
resolveSlots(instance, nextVNode.children)
|
resolveSlots(instance, nextVNode.children)
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchChildren(
|
const patchChildren = (
|
||||||
n1: HostVNode | null,
|
n1: HostVNode | null,
|
||||||
n2: HostVNode,
|
n2: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -1188,7 +1174,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean = false
|
optimized: boolean = false
|
||||||
) {
|
) => {
|
||||||
const c1 = n1 && n1.children
|
const c1 = n1 && n1.children
|
||||||
const prevShapeFlag = n1 ? n1.shapeFlag : 0
|
const prevShapeFlag = n1 ? n1.shapeFlag : 0
|
||||||
const c2 = n2.children
|
const c2 = n2.children
|
||||||
@ -1284,7 +1270,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchUnkeyedChildren(
|
const patchUnkeyedChildren = (
|
||||||
c1: HostVNode[],
|
c1: HostVNode[],
|
||||||
c2: HostVNodeChildren,
|
c2: HostVNodeChildren,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -1293,7 +1279,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
c1 = c1 || EMPTY_ARR
|
c1 = c1 || EMPTY_ARR
|
||||||
c2 = c2 || EMPTY_ARR
|
c2 = c2 || EMPTY_ARR
|
||||||
const oldLength = c1.length
|
const oldLength = c1.length
|
||||||
@ -1334,7 +1320,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can be all-keyed or mixed
|
// can be all-keyed or mixed
|
||||||
function patchKeyedChildren(
|
const patchKeyedChildren = (
|
||||||
c1: HostVNode[],
|
c1: HostVNode[],
|
||||||
c2: HostVNodeChildren,
|
c2: HostVNodeChildren,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
@ -1343,7 +1329,7 @@ function baseCreateRenderer<
|
|||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) => {
|
||||||
let i = 0
|
let i = 0
|
||||||
const l2 = c2.length
|
const l2 = c2.length
|
||||||
let e1 = c1.length - 1 // prev ending index
|
let e1 = c1.length - 1 // prev ending index
|
||||||
@ -1569,13 +1555,13 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function move(
|
const move = (
|
||||||
vnode: HostVNode,
|
vnode: HostVNode,
|
||||||
container: HostElement,
|
container: HostElement,
|
||||||
anchor: HostNode | null,
|
anchor: HostNode | null,
|
||||||
type: MoveType,
|
type: MoveType,
|
||||||
parentSuspense: HostSuspenseBoundary | null = null
|
parentSuspense: HostSuspenseBoundary | null = null
|
||||||
) {
|
) => {
|
||||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
||||||
move(vnode.component!.subTree, container, anchor, type)
|
move(vnode.component!.subTree, container, anchor, type)
|
||||||
return
|
return
|
||||||
@ -1624,12 +1610,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmount(
|
const unmount = (
|
||||||
vnode: HostVNode,
|
vnode: HostVNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean
|
||||||
) {
|
) => {
|
||||||
const { props, ref, children, dynamicChildren, shapeFlag } = vnode
|
const { props, ref, children, dynamicChildren, shapeFlag } = vnode
|
||||||
|
|
||||||
// unset ref
|
// unset ref
|
||||||
@ -1673,7 +1659,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(vnode: HostVNode) {
|
const remove = (vnode: HostVNode) => {
|
||||||
const { type, el, anchor, transition } = vnode
|
const { type, el, anchor, transition } = vnode
|
||||||
if (type === Fragment) {
|
if (type === Fragment) {
|
||||||
removeFragment(el!, anchor!)
|
removeFragment(el!, anchor!)
|
||||||
@ -1708,7 +1694,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFragment(cur: HostNode, end: HostNode) {
|
const removeFragment = (cur: HostNode, end: HostNode) => {
|
||||||
// For fragments, directly remove all contained DOM nodes.
|
// For fragments, directly remove all contained DOM nodes.
|
||||||
// (fragment child nodes cannot have transition)
|
// (fragment child nodes cannot have transition)
|
||||||
let next
|
let next
|
||||||
@ -1720,11 +1706,11 @@ function baseCreateRenderer<
|
|||||||
hostRemove(end)
|
hostRemove(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmountComponent(
|
const unmountComponent = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean
|
||||||
) {
|
) => {
|
||||||
if (__HMR__ && instance.type.__hmrId != null) {
|
if (__HMR__ && instance.type.__hmrId != null) {
|
||||||
unregisterHMR(instance)
|
unregisterHMR(instance)
|
||||||
}
|
}
|
||||||
@ -1779,19 +1765,19 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmountChildren(
|
const unmountChildren = (
|
||||||
children: HostVNode[],
|
children: HostVNode[],
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: HostSuspenseBoundary | null,
|
||||||
doRemove?: boolean,
|
doRemove?: boolean,
|
||||||
start: number = 0
|
start: number = 0
|
||||||
) {
|
) => {
|
||||||
for (let i = start; i < children.length; i++) {
|
for (let i = start; i < children.length; i++) {
|
||||||
unmount(children[i], parentComponent, parentSuspense, doRemove)
|
unmount(children[i], parentComponent, parentSuspense, doRemove)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNextHostNode(vnode: HostVNode): HostNode | null {
|
const getNextHostNode = (vnode: HostVNode): HostNode | null => {
|
||||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
||||||
return getNextHostNode(vnode.component!.subTree)
|
return getNextHostNode(vnode.component!.subTree)
|
||||||
}
|
}
|
||||||
@ -1801,12 +1787,12 @@ function baseCreateRenderer<
|
|||||||
return hostNextSibling((vnode.anchor || vnode.el)!)
|
return hostNextSibling((vnode.anchor || vnode.el)!)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRef(
|
const setRef = (
|
||||||
ref: string | Function | Ref,
|
ref: string | Function | Ref,
|
||||||
oldRef: string | Function | Ref | null,
|
oldRef: string | Function | Ref | null,
|
||||||
parent: ComponentInternalInstance,
|
parent: ComponentInternalInstance,
|
||||||
value: HostNode | ComponentPublicInstance | null
|
value: HostNode | ComponentPublicInstance | null
|
||||||
) {
|
) => {
|
||||||
const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs
|
const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs
|
||||||
const renderContext = toRaw(parent.renderContext)
|
const renderContext = toRaw(parent.renderContext)
|
||||||
|
|
||||||
@ -1855,6 +1841,20 @@ function baseCreateRenderer<
|
|||||||
container._vnode = vnode
|
container._vnode = vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const internals: RendererInternals<HostNode, HostElement> = {
|
||||||
|
patch,
|
||||||
|
unmount,
|
||||||
|
move,
|
||||||
|
next: getNextHostNode,
|
||||||
|
options
|
||||||
|
}
|
||||||
|
|
||||||
|
let hydrate: ReturnType<typeof createHydrationFunctions>[0] | undefined
|
||||||
|
let hydrateNode: ReturnType<typeof createHydrationFunctions>[1] | undefined
|
||||||
|
if (createHydrationFns) {
|
||||||
|
;[hydrate, hydrateNode] = createHydrationFns(mountComponent, hostPatchProp)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
render,
|
render,
|
||||||
hydrate,
|
hydrate,
|
||||||
|
Loading…
Reference in New Issue
Block a user