createVNode,
openBlock,
createBlock,
- Fragment
+ Fragment,
+ createCommentVNode
} from '../../src'
import { PatchFlags } from '@vue/shared/src'
const templateRendered = renderSlot({ default: slot }, 'default')
expect(templateRendered.dynamicChildren!.length).toBe(1)
})
+
+ // #2347 #2461
+ describe('only render valid slot content', () => {
+ it('should ignore slots that are all comments', () => {
+ let fallback
+ const vnode = renderSlot(
+ { default: () => [createCommentVNode('foo')] },
+ 'default',
+ undefined,
+ () => [(fallback = h('fallback'))]
+ )
+ expect(vnode.children).toEqual([fallback])
+ expect(vnode.patchFlag).toBe(PatchFlags.BAIL)
+ })
+
+ it('should ignore invalid slot content generated by nested slot', () => {
+ let fallback
+ const vnode = renderSlot(
+ { default: () => [renderSlot({}, 'foo')] },
+ 'default',
+ undefined,
+ () => [(fallback = h('fallback'))]
+ )
+ expect(vnode.children).toEqual([fallback])
+ expect(vnode.patchFlag).toBe(PatchFlags.BAIL)
+ })
+ })
})
import { Data } from '../component'
import { Slots, RawSlots } from '../componentSlots'
+import { Comment, isVNode } from '../vnode'
import {
VNodeArrayChildren,
openBlock,
// `renderSlot` we can be sure that it's template-based so we can force
// enable it.
isRenderingCompiledSlot++
- const rendered = (openBlock(),
- createBlock(
+ openBlock()
+ const validSlotContent = slot && ensureValidVNode(slot(props))
+ const rendered = createBlock(
Fragment,
{ key: props.key },
- slot ? slot(props) : fallback ? fallback() : [],
- (slots as RawSlots)._ === SlotFlags.STABLE
+ validSlotContent || (fallback ? fallback() : []),
+ validSlotContent && (slots as RawSlots)._ === SlotFlags.STABLE
? PatchFlags.STABLE_FRAGMENT
: PatchFlags.BAIL
- ))
+ )
isRenderingCompiledSlot--
return rendered
}
+
+function ensureValidVNode(vnodes: VNodeArrayChildren) {
+ return vnodes.some(child => {
+ if (!isVNode(child)) return true
+ if (child.type === Comment) return false
+ if (
+ child.type === Fragment &&
+ !ensureValidVNode(child.children as VNodeArrayChildren)
+ )
+ return false
+ return true
+ })
+ ? vnodes
+ : null
+}