fix(suspense): fix suspense nested child updates in template mode
fix #2214
This commit is contained in:
parent
128ec460ec
commit
0227b4a697
@ -14,6 +14,7 @@ import {
|
|||||||
onErrorCaptured,
|
onErrorCaptured,
|
||||||
shallowRef
|
shallowRef
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
|
||||||
describe('Suspense', () => {
|
describe('Suspense', () => {
|
||||||
const deps: Promise<any>[] = []
|
const deps: Promise<any>[] = []
|
||||||
@ -1068,4 +1069,28 @@ describe('Suspense', () => {
|
|||||||
expect(serializeInner(root)).toBe(`<div>two</div>`)
|
expect(serializeInner(root)).toBe(`<div>two</div>`)
|
||||||
expect(calls).toEqual([`one mounted`, `one unmounted`, `two mounted`])
|
expect(calls).toEqual([`one mounted`, `one unmounted`, `two mounted`])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #2214
|
||||||
|
// Since suspense renders its own root like a component, it should not patch
|
||||||
|
// its content in optimized mode.
|
||||||
|
test('should not miss nested element updates when used in templates', async () => {
|
||||||
|
const n = ref(1)
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
return { n }
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<Suspense>
|
||||||
|
<div><span>{{ n }}</span></div>
|
||||||
|
</Suspense>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
const root = document.createElement('div')
|
||||||
|
createApp(Comp).mount(root)
|
||||||
|
expect(root.innerHTML).toBe(`<div><span>1</span></div>`)
|
||||||
|
|
||||||
|
n.value++
|
||||||
|
await nextTick()
|
||||||
|
expect(root.innerHTML).toBe(`<div><span>2</span></div>`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -69,7 +69,6 @@ export const SuspenseImpl = {
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
isSVG,
|
isSVG,
|
||||||
optimized,
|
|
||||||
rendererInternals
|
rendererInternals
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -121,8 +120,7 @@ function mountSuspense(
|
|||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
// now check if we have encountered any async deps
|
// now check if we have encountered any async deps
|
||||||
if (suspense.deps > 0) {
|
if (suspense.deps > 0) {
|
||||||
@ -135,8 +133,7 @@ function mountSuspense(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
null, // fallback tree will not have suspense context
|
null, // fallback tree will not have suspense context
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
setActiveBranch(suspense, vnode.ssFallback!)
|
setActiveBranch(suspense, vnode.ssFallback!)
|
||||||
} else {
|
} else {
|
||||||
@ -152,7 +149,6 @@ function patchSuspense(
|
|||||||
anchor: RendererNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean,
|
|
||||||
{ p: patch, um: unmount, o: { createElement } }: RendererInternals
|
{ p: patch, um: unmount, o: { createElement } }: RendererInternals
|
||||||
) {
|
) {
|
||||||
const suspense = (n2.suspense = n1.suspense)!
|
const suspense = (n2.suspense = n1.suspense)!
|
||||||
@ -173,8 +169,7 @@ function patchSuspense(
|
|||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
if (suspense.deps <= 0) {
|
if (suspense.deps <= 0) {
|
||||||
suspense.resolve()
|
suspense.resolve()
|
||||||
@ -186,8 +181,7 @@ function patchSuspense(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
null, // fallback tree will not have suspense context
|
null, // fallback tree will not have suspense context
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
setActiveBranch(suspense, newFallback)
|
setActiveBranch(suspense, newFallback)
|
||||||
}
|
}
|
||||||
@ -220,8 +214,7 @@ function patchSuspense(
|
|||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
if (suspense.deps <= 0) {
|
if (suspense.deps <= 0) {
|
||||||
suspense.resolve()
|
suspense.resolve()
|
||||||
@ -233,8 +226,7 @@ function patchSuspense(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
null, // fallback tree will not have suspense context
|
null, // fallback tree will not have suspense context
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
setActiveBranch(suspense, newFallback)
|
setActiveBranch(suspense, newFallback)
|
||||||
}
|
}
|
||||||
@ -247,8 +239,7 @@ function patchSuspense(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
// force resolve
|
// force resolve
|
||||||
suspense.resolve(true)
|
suspense.resolve(true)
|
||||||
@ -261,8 +252,7 @@ function patchSuspense(
|
|||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
if (suspense.deps <= 0) {
|
if (suspense.deps <= 0) {
|
||||||
suspense.resolve()
|
suspense.resolve()
|
||||||
@ -279,8 +269,7 @@ function patchSuspense(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
setActiveBranch(suspense, newBranch)
|
setActiveBranch(suspense, newBranch)
|
||||||
} else {
|
} else {
|
||||||
@ -300,8 +289,7 @@ function patchSuspense(
|
|||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
suspense,
|
suspense,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
if (suspense.deps <= 0) {
|
if (suspense.deps <= 0) {
|
||||||
// incoming branch has no async deps, resolve now.
|
// incoming branch has no async deps, resolve now.
|
||||||
@ -327,7 +315,6 @@ export interface SuspenseBoundary {
|
|||||||
parent: SuspenseBoundary | null
|
parent: SuspenseBoundary | null
|
||||||
parentComponent: ComponentInternalInstance | null
|
parentComponent: ComponentInternalInstance | null
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
optimized: boolean
|
|
||||||
container: RendererElement
|
container: RendererElement
|
||||||
hiddenContainer: RendererElement
|
hiddenContainer: RendererElement
|
||||||
anchor: RendererNode | null
|
anchor: RendererNode | null
|
||||||
@ -392,7 +379,6 @@ function createSuspenseBoundary(
|
|||||||
parent,
|
parent,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
isSVG,
|
isSVG,
|
||||||
optimized,
|
|
||||||
container,
|
container,
|
||||||
hiddenContainer,
|
hiddenContainer,
|
||||||
anchor,
|
anchor,
|
||||||
@ -499,8 +485,7 @@ function createSuspenseBoundary(
|
|||||||
activeBranch,
|
activeBranch,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
container,
|
container,
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
} = suspense
|
} = suspense
|
||||||
|
|
||||||
// invoke @fallback event
|
// invoke @fallback event
|
||||||
@ -522,8 +507,7 @@ function createSuspenseBoundary(
|
|||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
null, // fallback tree will not have suspense context
|
null, // fallback tree will not have suspense context
|
||||||
isSVG,
|
isSVG
|
||||||
optimized
|
|
||||||
)
|
)
|
||||||
setActiveBranch(suspense, fallbackVNode)
|
setActiveBranch(suspense, fallbackVNode)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user