fix(suspense): fix dynamicChildren tracking when suspense root is a block itself
e.g. `<slot>` inside suspense fix #4183, fix #4198
This commit is contained in:
parent
1867591e7c
commit
51ee84fc6a
@ -22,7 +22,8 @@ import {
|
|||||||
SetupContext,
|
SetupContext,
|
||||||
createApp,
|
createApp,
|
||||||
FunctionalComponent,
|
FunctionalComponent,
|
||||||
renderList
|
renderList,
|
||||||
|
onUnmounted
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { PatchFlags, SlotFlags } from '@vue/shared'
|
import { PatchFlags, SlotFlags } from '@vue/shared'
|
||||||
import { SuspenseImpl } from '../src/components/Suspense'
|
import { SuspenseImpl } from '../src/components/Suspense'
|
||||||
@ -826,6 +827,55 @@ describe('renderer: optimized mode', () => {
|
|||||||
expect(inner(root)).toBe('<div><div>true</div></div>')
|
expect(inner(root)).toBe('<div><div>true</div></div>')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #4183
|
||||||
|
test('should not take unmount children fast path /w Suspense', async () => {
|
||||||
|
const show = ref(true)
|
||||||
|
const spyUnmounted = jest.fn()
|
||||||
|
|
||||||
|
const Parent = {
|
||||||
|
setup(props: any, { slots }: SetupContext) {
|
||||||
|
return () => (
|
||||||
|
openBlock(),
|
||||||
|
createBlock(SuspenseImpl, null, {
|
||||||
|
default: withCtx(() => [renderSlot(slots, 'default')]),
|
||||||
|
_: SlotFlags.FORWARDED
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
onUnmounted(spyUnmounted)
|
||||||
|
return () => createVNode('div', null, show.value, PatchFlags.TEXT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
render() {
|
||||||
|
return show.value
|
||||||
|
? (openBlock(),
|
||||||
|
createBlock(
|
||||||
|
Parent,
|
||||||
|
{ key: 0 },
|
||||||
|
{
|
||||||
|
default: withCtx(() => [createVNode(Child)]),
|
||||||
|
_: SlotFlags.STABLE
|
||||||
|
}
|
||||||
|
))
|
||||||
|
: createCommentVNode('v-if', true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.mount(root)
|
||||||
|
expect(inner(root)).toBe('<div>true</div>')
|
||||||
|
|
||||||
|
show.value = false
|
||||||
|
await nextTick()
|
||||||
|
expect(inner(root)).toBe('<!--v-if-->')
|
||||||
|
expect(spyUnmounted).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
// #3881
|
// #3881
|
||||||
// root cause: fragment inside a compiled slot passed to component which
|
// root cause: fragment inside a compiled slot passed to component which
|
||||||
// programmatically invokes the slot. The entire slot should de-opt but
|
// programmatically invokes the slot. The entire slot should de-opt but
|
||||||
|
@ -749,7 +749,7 @@ function normalizeSuspenseSlot(s: any) {
|
|||||||
s = singleChild
|
s = singleChild
|
||||||
}
|
}
|
||||||
s = normalizeVNode(s)
|
s = normalizeVNode(s)
|
||||||
if (block) {
|
if (block && !s.dynamicChildren) {
|
||||||
s.dynamicChildren = block.filter(c => c !== s)
|
s.dynamicChildren = block.filter(c => c !== s)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
Loading…
Reference in New Issue
Block a user