mirror of https://github.com/vuejs/core.git
fix(suspense): don't immediately resolve suspense on last dep unmount (#13456)
close #13453
This commit is contained in:
parent
0562548ab3
commit
a8713159ee
|
@ -17,6 +17,8 @@ import {
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
ref,
|
ref,
|
||||||
render,
|
render,
|
||||||
|
renderList,
|
||||||
|
renderSlot,
|
||||||
resolveDynamicComponent,
|
resolveDynamicComponent,
|
||||||
serializeInner,
|
serializeInner,
|
||||||
shallowRef,
|
shallowRef,
|
||||||
|
@ -2161,6 +2163,80 @@ describe('Suspense', () => {
|
||||||
await Promise.all(deps)
|
await Promise.all(deps)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #13453
|
||||||
|
test('add new async deps during patching', async () => {
|
||||||
|
const getComponent = (type: string) => {
|
||||||
|
if (type === 'A') {
|
||||||
|
return defineAsyncComponent({
|
||||||
|
setup() {
|
||||||
|
return () => h('div', 'A')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return defineAsyncComponent({
|
||||||
|
setup() {
|
||||||
|
return () => h('div', 'B')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const types = ref(['A'])
|
||||||
|
const add = async () => {
|
||||||
|
types.value.push('B')
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = async () => {
|
||||||
|
// mount Suspense B
|
||||||
|
// [Suspense A] -> [Suspense A(pending), Suspense B(pending)]
|
||||||
|
await add()
|
||||||
|
// patch Suspense B (still pending)
|
||||||
|
// [Suspense A(pending), Suspense B(pending)] -> [Suspense B(pending)]
|
||||||
|
types.value.shift()
|
||||||
|
}
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
render(this: any) {
|
||||||
|
return h(Fragment, null, [
|
||||||
|
renderList(types.value, type => {
|
||||||
|
return h(
|
||||||
|
Suspense,
|
||||||
|
{ key: type },
|
||||||
|
{
|
||||||
|
default: () => [
|
||||||
|
renderSlot(this.$slots, 'default', { type: type }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const App = {
|
||||||
|
setup() {
|
||||||
|
return () =>
|
||||||
|
h(Comp, null, {
|
||||||
|
default: (params: any) => [h(getComponent(params.type))],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(App), root)
|
||||||
|
expect(serializeInner(root)).toBe(`<!---->`)
|
||||||
|
|
||||||
|
await Promise.all(deps)
|
||||||
|
expect(serializeInner(root)).toBe(`<div>A</div>`)
|
||||||
|
|
||||||
|
update()
|
||||||
|
await nextTick()
|
||||||
|
// wait for both A and B to resolve
|
||||||
|
await Promise.all(deps)
|
||||||
|
// wait for new B to resolve
|
||||||
|
await Promise.all(deps)
|
||||||
|
expect(serializeInner(root)).toBe(`<div>B</div>`)
|
||||||
|
})
|
||||||
|
|
||||||
describe('warnings', () => {
|
describe('warnings', () => {
|
||||||
// base function to check if a combination of slots warns or not
|
// base function to check if a combination of slots warns or not
|
||||||
function baseCheckWarn(
|
function baseCheckWarn(
|
||||||
|
|
|
@ -2326,24 +2326,6 @@ function baseCreateRenderer(
|
||||||
instance.isUnmounted = true
|
instance.isUnmounted = true
|
||||||
}, parentSuspense)
|
}, parentSuspense)
|
||||||
|
|
||||||
// A component with async dep inside a pending suspense is unmounted before
|
|
||||||
// its async dep resolves. This should remove the dep from the suspense, and
|
|
||||||
// cause the suspense to resolve immediately if that was the last dep.
|
|
||||||
if (
|
|
||||||
__FEATURE_SUSPENSE__ &&
|
|
||||||
parentSuspense &&
|
|
||||||
parentSuspense.pendingBranch &&
|
|
||||||
!parentSuspense.isUnmounted &&
|
|
||||||
instance.asyncDep &&
|
|
||||||
!instance.asyncResolved &&
|
|
||||||
instance.suspenseId === parentSuspense.pendingId
|
|
||||||
) {
|
|
||||||
parentSuspense.deps--
|
|
||||||
if (parentSuspense.deps === 0) {
|
|
||||||
parentSuspense.resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
||||||
devtoolsComponentRemoved(instance)
|
devtoolsComponentRemoved(instance)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue