|
@@ -13,8 +13,7 @@ import {
|
|
|
ComponentInternalInstance,
|
|
ComponentInternalInstance,
|
|
|
createComponentInstance,
|
|
createComponentInstance,
|
|
|
setupStatefulComponent,
|
|
setupStatefulComponent,
|
|
|
- handleSetupResult,
|
|
|
|
|
- setCurrentInstance
|
|
|
|
|
|
|
+ handleSetupResult
|
|
|
} from './component'
|
|
} from './component'
|
|
|
import {
|
|
import {
|
|
|
renderComponentRoot,
|
|
renderComponentRoot,
|
|
@@ -49,7 +48,6 @@ import {
|
|
|
createSuspenseBoundary,
|
|
createSuspenseBoundary,
|
|
|
normalizeSuspenseChildren
|
|
normalizeSuspenseChildren
|
|
|
} from './suspense'
|
|
} from './suspense'
|
|
|
-import { provide } from './apiInject'
|
|
|
|
|
|
|
|
|
|
const prodEffectOptions = {
|
|
const prodEffectOptions = {
|
|
|
scheduler: queueJob
|
|
scheduler: queueJob
|
|
@@ -88,9 +86,11 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
prevChildren?: VNode<HostNode, HostElement>[],
|
|
prevChildren?: VNode<HostNode, HostElement>[],
|
|
|
parentComponent?: ComponentInternalInstance | null,
|
|
parentComponent?: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
|
|
|
unmountChildren?: (
|
|
unmountChildren?: (
|
|
|
children: VNode<HostNode, HostElement>[],
|
|
children: VNode<HostNode, HostElement>[],
|
|
|
- parentComponent: ComponentInternalInstance | null
|
|
|
|
|
|
|
+ parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: SuspenseBoundary<HostNode, HostElement> | null
|
|
|
) => void
|
|
) => void
|
|
|
): void
|
|
): void
|
|
|
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
|
|
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
|
|
@@ -136,6 +136,7 @@ export function createRenderer<
|
|
|
} {
|
|
} {
|
|
|
type HostVNode = VNode<HostNode, HostElement>
|
|
type HostVNode = VNode<HostNode, HostElement>
|
|
|
type HostVNodeChildren = VNodeChildren<HostNode, HostElement>
|
|
type HostVNodeChildren = VNodeChildren<HostNode, HostElement>
|
|
|
|
|
+ type HostSuspsenseBoundary = SuspenseBoundary<HostNode, HostElement>
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
insert: hostInsert,
|
|
insert: hostInsert,
|
|
@@ -157,13 +158,14 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null = null,
|
|
anchor: HostNode | null = null,
|
|
|
parentComponent: ComponentInternalInstance | null = null,
|
|
parentComponent: ComponentInternalInstance | null = null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | 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 && !isSameType(n1, n2)) {
|
|
if (n1 != null && !isSameType(n1, n2)) {
|
|
|
anchor = getNextHostNode(n1)
|
|
anchor = getNextHostNode(n1)
|
|
|
- unmount(n1, parentComponent, true)
|
|
|
|
|
|
|
+ unmount(n1, parentComponent, parentSuspense, true)
|
|
|
n1 = null
|
|
n1 = null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -182,6 +184,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -193,6 +196,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -205,6 +209,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -220,6 +225,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -230,6 +236,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -278,13 +285,21 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
|
if (n1 == null) {
|
|
if (n1 == null) {
|
|
|
- mountElement(n2, container, anchor, parentComponent, isSVG)
|
|
|
|
|
|
|
+ mountElement(
|
|
|
|
|
+ n2,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
} else {
|
|
} else {
|
|
|
- patchElement(n1, n2, parentComponent, isSVG, optimized)
|
|
|
|
|
|
|
+ patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized)
|
|
|
}
|
|
}
|
|
|
if (n2.ref !== null && parentComponent !== null) {
|
|
if (n2.ref !== null && parentComponent !== null) {
|
|
|
setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el)
|
|
setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el)
|
|
@@ -296,6 +311,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean
|
|
isSVG: boolean
|
|
|
) {
|
|
) {
|
|
|
const tag = vnode.type as string
|
|
const tag = vnode.type as string
|
|
@@ -319,6 +335,7 @@ export function createRenderer<
|
|
|
el,
|
|
el,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -335,12 +352,21 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: 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] = normalizeVNode(children[i]))
|
|
const child = (children[i] = normalizeVNode(children[i]))
|
|
|
- patch(null, child, container, anchor, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patch(
|
|
|
|
|
+ null,
|
|
|
|
|
+ child,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -348,6 +374,7 @@ export function createRenderer<
|
|
|
n1: HostVNode,
|
|
n1: HostVNode,
|
|
|
n2: HostVNode,
|
|
n2: HostVNode,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
@@ -368,7 +395,15 @@ export function createRenderer<
|
|
|
|
|
|
|
|
if (patchFlag & PatchFlags.FULL_PROPS) {
|
|
if (patchFlag & PatchFlags.FULL_PROPS) {
|
|
|
// element props contain dynamic keys, full diff needed
|
|
// element props contain dynamic keys, full diff needed
|
|
|
- patchProps(el, n2, oldProps, newProps, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patchProps(
|
|
|
|
|
+ el,
|
|
|
|
|
+ n2,
|
|
|
|
|
+ oldProps,
|
|
|
|
|
+ newProps,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
} else {
|
|
} else {
|
|
|
// class
|
|
// class
|
|
|
// this flag is matched when the element has dynamic class bindings.
|
|
// this flag is matched when the element has dynamic class bindings.
|
|
@@ -406,6 +441,7 @@ export function createRenderer<
|
|
|
isSVG,
|
|
isSVG,
|
|
|
n1.children as HostVNode[],
|
|
n1.children as HostVNode[],
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
unmountChildren
|
|
unmountChildren
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -424,7 +460,15 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
} else if (!optimized) {
|
|
} else if (!optimized) {
|
|
|
// unoptimized, full diff
|
|
// unoptimized, full diff
|
|
|
- patchProps(el, n2, oldProps, newProps, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patchProps(
|
|
|
|
|
+ el,
|
|
|
|
|
+ n2,
|
|
|
|
|
+ oldProps,
|
|
|
|
|
+ newProps,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (dynamicChildren != null) {
|
|
if (dynamicChildren != null) {
|
|
@@ -437,13 +481,14 @@ export function createRenderer<
|
|
|
el,
|
|
el,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
true
|
|
true
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
} else if (!optimized) {
|
|
} else if (!optimized) {
|
|
|
// full diff
|
|
// full diff
|
|
|
- patchChildren(n1, n2, el, null, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (newProps.vnodeUpdated != null) {
|
|
if (newProps.vnodeUpdated != null) {
|
|
@@ -459,6 +504,7 @@ export function createRenderer<
|
|
|
oldProps: any,
|
|
oldProps: any,
|
|
|
newProps: any,
|
|
newProps: any,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean
|
|
isSVG: boolean
|
|
|
) {
|
|
) {
|
|
|
if (oldProps !== newProps) {
|
|
if (oldProps !== newProps) {
|
|
@@ -475,6 +521,7 @@ export function createRenderer<
|
|
|
isSVG,
|
|
isSVG,
|
|
|
vnode.children as HostVNode[],
|
|
vnode.children as HostVNode[],
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
unmountChildren
|
|
unmountChildren
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -491,6 +538,7 @@ export function createRenderer<
|
|
|
isSVG,
|
|
isSVG,
|
|
|
vnode.children as HostVNode[],
|
|
vnode.children as HostVNode[],
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
unmountChildren
|
|
unmountChildren
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -505,6 +553,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
@@ -525,6 +574,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
fragmentEndAnchor,
|
|
fragmentEndAnchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
} else {
|
|
} else {
|
|
@@ -534,6 +584,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
fragmentEndAnchor,
|
|
fragmentEndAnchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -546,6 +597,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
@@ -564,6 +616,7 @@ export function createRenderer<
|
|
|
target,
|
|
target,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -576,7 +629,15 @@ export function createRenderer<
|
|
|
if (patchFlag === PatchFlags.TEXT) {
|
|
if (patchFlag === PatchFlags.TEXT) {
|
|
|
hostSetElementText(target, children as string)
|
|
hostSetElementText(target, children as string)
|
|
|
} else if (!optimized) {
|
|
} else if (!optimized) {
|
|
|
- patchChildren(n1, n2, target, null, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patchChildren(
|
|
|
|
|
+ n1,
|
|
|
|
|
+ n2,
|
|
|
|
|
+ target,
|
|
|
|
|
+ null,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
// target changed
|
|
// target changed
|
|
|
if (targetSelector !== (n1.props && n1.props.target)) {
|
|
if (targetSelector !== (n1.props && n1.props.target)) {
|
|
@@ -608,9 +669,9 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
- optimized: boolean,
|
|
|
|
|
- parentSuspense: SuspenseBoundary<HostNode, HostElement> | null = null
|
|
|
|
|
|
|
+ optimized: boolean
|
|
|
) {
|
|
) {
|
|
|
if (n1 == null) {
|
|
if (n1 == null) {
|
|
|
const suspense = (n2.suspense = createSuspenseBoundary(
|
|
const suspense = (n2.suspense = createSuspenseBoundary(
|
|
@@ -623,7 +684,7 @@ export function createRenderer<
|
|
|
function resolveSuspense() {
|
|
function resolveSuspense() {
|
|
|
const { subTree, fallbackTree, bufferedJobs, vnode } = suspense
|
|
const { subTree, fallbackTree, bufferedJobs, vnode } = suspense
|
|
|
// unmount fallback tree
|
|
// unmount fallback tree
|
|
|
- unmount(fallbackTree as HostVNode, parentComponent, true)
|
|
|
|
|
|
|
+ unmount(fallbackTree as HostVNode, parentComponent, suspense, true)
|
|
|
// move content from off-dom container to actual container
|
|
// move content from off-dom container to actual container
|
|
|
move(subTree as HostVNode, container, anchor)
|
|
move(subTree as HostVNode, container, anchor)
|
|
|
const el = (vnode.el = (subTree as HostVNode).el as HostNode)
|
|
const el = (vnode.el = (subTree as HostVNode).el as HostNode)
|
|
@@ -656,13 +717,6 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // TODO pass it down as an arg instead
|
|
|
|
|
- if (parentComponent) {
|
|
|
|
|
- setCurrentInstance(parentComponent)
|
|
|
|
|
- provide('suspense', suspense)
|
|
|
|
|
- setCurrentInstance(null)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
const { content, fallback } = normalizeSuspenseChildren(n2)
|
|
const { content, fallback } = normalizeSuspenseChildren(n2)
|
|
|
suspense.subTree = content
|
|
suspense.subTree = content
|
|
|
suspense.fallbackTree = fallback
|
|
suspense.fallbackTree = fallback
|
|
@@ -675,6 +729,7 @@ export function createRenderer<
|
|
|
suspense.container,
|
|
suspense.container,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ suspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -687,6 +742,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ suspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -696,10 +752,7 @@ export function createRenderer<
|
|
|
suspense.resolve()
|
|
suspense.resolve()
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- const suspense = (n2.suspense = n1.suspense) as SuspenseBoundary<
|
|
|
|
|
- HostNode,
|
|
|
|
|
- HostElement
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ const suspense = (n2.suspense = n1.suspense) as HostSuspsenseBoundary
|
|
|
suspense.vnode = n2
|
|
suspense.vnode = n2
|
|
|
const { content, fallback } = normalizeSuspenseChildren(n2)
|
|
const { content, fallback } = normalizeSuspenseChildren(n2)
|
|
|
const oldSubTree = (suspense.oldSubTree = suspense.subTree)
|
|
const oldSubTree = (suspense.oldSubTree = suspense.subTree)
|
|
@@ -713,6 +766,7 @@ export function createRenderer<
|
|
|
suspense.container,
|
|
suspense.container,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ suspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -724,6 +778,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ suspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -739,6 +794,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ suspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -753,11 +809,19 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
|
if (n1 == null) {
|
|
if (n1 == null) {
|
|
|
- mountComponent(n2, container, anchor, parentComponent, isSVG)
|
|
|
|
|
|
|
+ mountComponent(
|
|
|
|
|
+ n2,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
} else {
|
|
} else {
|
|
|
const instance = (n2.component =
|
|
const instance = (n2.component =
|
|
|
n1.component) as ComponentInternalInstance
|
|
n1.component) as ComponentInternalInstance
|
|
@@ -796,6 +860,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean
|
|
isSVG: boolean
|
|
|
) {
|
|
) {
|
|
|
const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(
|
|
const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(
|
|
@@ -820,21 +885,26 @@ export function createRenderer<
|
|
|
// setup() is async. This component relies on async logic to be resolved
|
|
// setup() is async. This component relies on async logic to be resolved
|
|
|
// before proceeding
|
|
// before proceeding
|
|
|
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
|
|
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
|
|
|
- // TODO use context suspense
|
|
|
|
|
- const suspense = (instance as any).provides.suspense
|
|
|
|
|
- if (!suspense) {
|
|
|
|
|
|
|
+ if (!parentSuspense) {
|
|
|
throw new Error('Async component without a suspense boundary!')
|
|
throw new Error('Async component without a suspense boundary!')
|
|
|
}
|
|
}
|
|
|
- suspense.deps++
|
|
|
|
|
|
|
+ parentSuspense.deps++
|
|
|
instance.asyncDep.then(asyncSetupResult => {
|
|
instance.asyncDep.then(asyncSetupResult => {
|
|
|
- suspense.deps--
|
|
|
|
|
|
|
+ parentSuspense.deps--
|
|
|
// retry from this component
|
|
// retry from this component
|
|
|
instance.asyncResolved = true
|
|
instance.asyncResolved = true
|
|
|
handleSetupResult(instance, asyncSetupResult)
|
|
handleSetupResult(instance, asyncSetupResult)
|
|
|
- setupRenderEffect(instance, initialVNode, container, anchor, isSVG)
|
|
|
|
|
|
|
+ setupRenderEffect(
|
|
|
|
|
+ instance,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ initialVNode,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
updateHOCHostEl(instance, initialVNode.el as HostNode)
|
|
updateHOCHostEl(instance, initialVNode.el as HostNode)
|
|
|
- if (suspense.deps === 0) {
|
|
|
|
|
- suspense.resolve()
|
|
|
|
|
|
|
+ if (parentSuspense.deps === 0) {
|
|
|
|
|
+ parentSuspense.resolve()
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
// give it a placeholder
|
|
// give it a placeholder
|
|
@@ -844,7 +914,14 @@ export function createRenderer<
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- setupRenderEffect(instance, initialVNode, container, anchor, isSVG)
|
|
|
|
|
|
|
+ setupRenderEffect(
|
|
|
|
|
+ instance,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ initialVNode,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
if (__DEV__) {
|
|
if (__DEV__) {
|
|
|
popWarningContext()
|
|
popWarningContext()
|
|
@@ -853,6 +930,7 @@ export function createRenderer<
|
|
|
|
|
|
|
|
function setupRenderEffect(
|
|
function setupRenderEffect(
|
|
|
instance: ComponentInternalInstance,
|
|
instance: ComponentInternalInstance,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
initialVNode: HostVNode,
|
|
initialVNode: HostVNode,
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
@@ -867,7 +945,7 @@ export function createRenderer<
|
|
|
if (instance.bm !== null) {
|
|
if (instance.bm !== null) {
|
|
|
invokeHooks(instance.bm)
|
|
invokeHooks(instance.bm)
|
|
|
}
|
|
}
|
|
|
- patch(null, subTree, container, anchor, instance, isSVG)
|
|
|
|
|
|
|
+ patch(null, subTree, container, anchor, instance, parentSuspense, isSVG)
|
|
|
initialVNode.el = subTree.el
|
|
initialVNode.el = subTree.el
|
|
|
// mounted hook
|
|
// mounted hook
|
|
|
if (instance.m !== null) {
|
|
if (instance.m !== null) {
|
|
@@ -911,6 +989,7 @@ export function createRenderer<
|
|
|
// anchor may have changed if it's in a fragment
|
|
// anchor may have changed if it's in a fragment
|
|
|
getNextHostNode(prevTree),
|
|
getNextHostNode(prevTree),
|
|
|
instance,
|
|
instance,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
let current = instance.vnode
|
|
let current = instance.vnode
|
|
@@ -949,6 +1028,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean = false
|
|
optimized: boolean = false
|
|
|
) {
|
|
) {
|
|
@@ -968,6 +1048,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -980,6 +1061,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -991,7 +1073,7 @@ export function createRenderer<
|
|
|
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
|
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
|
|
// text children fast path
|
|
// text children fast path
|
|
|
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
|
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
|
|
- unmountChildren(c1 as HostVNode[], parentComponent)
|
|
|
|
|
|
|
+ unmountChildren(c1 as HostVNode[], parentComponent, parentSuspense)
|
|
|
}
|
|
}
|
|
|
if (c2 !== c1) {
|
|
if (c2 !== c1) {
|
|
|
hostSetElementText(container, c2 as string)
|
|
hostSetElementText(container, c2 as string)
|
|
@@ -1007,12 +1089,18 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
|
} else {
|
|
} else {
|
|
|
// no new children, just unmount old
|
|
// no new children, just unmount old
|
|
|
- unmountChildren(c1 as HostVNode[], parentComponent, true)
|
|
|
|
|
|
|
+ unmountChildren(
|
|
|
|
|
+ c1 as HostVNode[],
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ true
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// prev children was text OR null
|
|
// prev children was text OR null
|
|
@@ -1027,6 +1115,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -1040,6 +1129,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
anchor: HostNode | null,
|
|
anchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
@@ -1057,16 +1147,25 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
if (oldLength > newLength) {
|
|
if (oldLength > newLength) {
|
|
|
// remove old
|
|
// remove old
|
|
|
- unmountChildren(c1, parentComponent, true, commonLength)
|
|
|
|
|
|
|
+ unmountChildren(c1, parentComponent, parentSuspense, true, commonLength)
|
|
|
} else {
|
|
} else {
|
|
|
// mount new
|
|
// mount new
|
|
|
- mountChildren(c2, container, anchor, parentComponent, isSVG, commonLength)
|
|
|
|
|
|
|
+ mountChildren(
|
|
|
|
|
+ c2,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG,
|
|
|
|
|
+ commonLength
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1077,6 +1176,7 @@ export function createRenderer<
|
|
|
container: HostElement,
|
|
container: HostElement,
|
|
|
parentAnchor: HostNode | null,
|
|
parentAnchor: HostNode | null,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
isSVG: boolean,
|
|
isSVG: boolean,
|
|
|
optimized: boolean
|
|
optimized: boolean
|
|
|
) {
|
|
) {
|
|
@@ -1098,6 +1198,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
parentAnchor,
|
|
parentAnchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -1120,6 +1221,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
parentAnchor,
|
|
parentAnchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -1149,6 +1251,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
anchor,
|
|
anchor,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG
|
|
isSVG
|
|
|
)
|
|
)
|
|
|
i++
|
|
i++
|
|
@@ -1165,7 +1268,7 @@ export function createRenderer<
|
|
|
// i = 0, e1 = 0, e2 = -1
|
|
// i = 0, e1 = 0, e2 = -1
|
|
|
else if (i > e2) {
|
|
else if (i > e2) {
|
|
|
while (i <= e1) {
|
|
while (i <= e1) {
|
|
|
- unmount(c1[i], parentComponent, true)
|
|
|
|
|
|
|
+ unmount(c1[i], parentComponent, parentSuspense, true)
|
|
|
i++
|
|
i++
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1214,7 +1317,7 @@ export function createRenderer<
|
|
|
const prevChild = c1[i]
|
|
const prevChild = c1[i]
|
|
|
if (patched >= toBePatched) {
|
|
if (patched >= toBePatched) {
|
|
|
// all new children have been patched so this can only be a removal
|
|
// all new children have been patched so this can only be a removal
|
|
|
- unmount(prevChild, parentComponent, true)
|
|
|
|
|
|
|
+ unmount(prevChild, parentComponent, parentSuspense, true)
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
let newIndex
|
|
let newIndex
|
|
@@ -1230,7 +1333,7 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if (newIndex === undefined) {
|
|
if (newIndex === undefined) {
|
|
|
- unmount(prevChild, parentComponent, true)
|
|
|
|
|
|
|
+ unmount(prevChild, parentComponent, parentSuspense, true)
|
|
|
} else {
|
|
} else {
|
|
|
newIndexToOldIndexMap[newIndex - s2] = i + 1
|
|
newIndexToOldIndexMap[newIndex - s2] = i + 1
|
|
|
if (newIndex >= maxNewIndexSoFar) {
|
|
if (newIndex >= maxNewIndexSoFar) {
|
|
@@ -1244,6 +1347,7 @@ export function createRenderer<
|
|
|
container,
|
|
container,
|
|
|
null,
|
|
null,
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
isSVG,
|
|
isSVG,
|
|
|
optimized
|
|
optimized
|
|
|
)
|
|
)
|
|
@@ -1267,7 +1371,15 @@ export function createRenderer<
|
|
|
: parentAnchor
|
|
: parentAnchor
|
|
|
if (newIndexToOldIndexMap[i] === 0) {
|
|
if (newIndexToOldIndexMap[i] === 0) {
|
|
|
// mount new
|
|
// mount new
|
|
|
- patch(null, nextChild, container, anchor, parentComponent, isSVG)
|
|
|
|
|
|
|
+ patch(
|
|
|
|
|
+ null,
|
|
|
|
|
+ nextChild,
|
|
|
|
|
+ container,
|
|
|
|
|
+ anchor,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ isSVG
|
|
|
|
|
+ )
|
|
|
} else if (moved) {
|
|
} else if (moved) {
|
|
|
// move if:
|
|
// move if:
|
|
|
// There is no stable subsequence (e.g. a reverse)
|
|
// There is no stable subsequence (e.g. a reverse)
|
|
@@ -1310,6 +1422,7 @@ export function createRenderer<
|
|
|
function unmount(
|
|
function unmount(
|
|
|
vnode: HostVNode,
|
|
vnode: HostVNode,
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
doRemove?: boolean
|
|
doRemove?: boolean
|
|
|
) {
|
|
) {
|
|
|
const {
|
|
const {
|
|
@@ -1330,12 +1443,17 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (component != null) {
|
|
if (component != null) {
|
|
|
- unmountComponent(component, doRemove)
|
|
|
|
|
|
|
+ unmountComponent(component, parentSuspense, doRemove)
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (__FEATURE_SUSPENSE__ && suspense != null) {
|
|
if (__FEATURE_SUSPENSE__ && suspense != null) {
|
|
|
- unmount(suspense.subTree as HostVNode, parentComponent, doRemove)
|
|
|
|
|
|
|
+ unmount(
|
|
|
|
|
+ suspense.subTree as HostVNode,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ doRemove
|
|
|
|
|
+ )
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1345,11 +1463,17 @@ export function createRenderer<
|
|
|
|
|
|
|
|
const shouldRemoveChildren = type === Fragment && doRemove
|
|
const shouldRemoveChildren = type === Fragment && doRemove
|
|
|
if (dynamicChildren != null) {
|
|
if (dynamicChildren != null) {
|
|
|
- unmountChildren(dynamicChildren, parentComponent, shouldRemoveChildren)
|
|
|
|
|
|
|
+ unmountChildren(
|
|
|
|
|
+ dynamicChildren,
|
|
|
|
|
+ parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
|
|
+ shouldRemoveChildren
|
|
|
|
|
+ )
|
|
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
|
|
unmountChildren(
|
|
unmountChildren(
|
|
|
children as HostVNode[],
|
|
children as HostVNode[],
|
|
|
parentComponent,
|
|
parentComponent,
|
|
|
|
|
+ parentSuspense,
|
|
|
shouldRemoveChildren
|
|
shouldRemoveChildren
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
@@ -1368,6 +1492,7 @@ export function createRenderer<
|
|
|
|
|
|
|
|
function unmountComponent(
|
|
function unmountComponent(
|
|
|
instance: ComponentInternalInstance,
|
|
instance: ComponentInternalInstance,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | null,
|
|
|
doRemove?: boolean
|
|
doRemove?: boolean
|
|
|
) {
|
|
) {
|
|
|
const { bum, effects, update, subTree, um } = instance
|
|
const { bum, effects, update, subTree, um } = instance
|
|
@@ -1381,7 +1506,7 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
stop(update)
|
|
stop(update)
|
|
|
- unmount(subTree, instance, doRemove)
|
|
|
|
|
|
|
+ unmount(subTree, instance, parentSuspense, doRemove)
|
|
|
// unmounted hook
|
|
// unmounted hook
|
|
|
if (um !== null) {
|
|
if (um !== null) {
|
|
|
queuePostFlushCb(um)
|
|
queuePostFlushCb(um)
|
|
@@ -1391,11 +1516,12 @@ export function createRenderer<
|
|
|
function unmountChildren(
|
|
function unmountChildren(
|
|
|
children: HostVNode[],
|
|
children: HostVNode[],
|
|
|
parentComponent: ComponentInternalInstance | null,
|
|
parentComponent: ComponentInternalInstance | null,
|
|
|
|
|
+ parentSuspense: HostSuspsenseBoundary | 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, doRemove)
|
|
|
|
|
|
|
+ unmount(children[i], parentComponent, parentSuspense, doRemove)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1457,7 +1583,7 @@ export function createRenderer<
|
|
|
}
|
|
}
|
|
|
if (vnode == null) {
|
|
if (vnode == null) {
|
|
|
if (container._vnode) {
|
|
if (container._vnode) {
|
|
|
- unmount(container._vnode, null, true)
|
|
|
|
|
|
|
+ unmount(container._vnode, null, null, true)
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
patch(container._vnode || null, vnode, container)
|
|
patch(container._vnode || null, vnode, container)
|