File tree 2 files changed +51
-6
lines changed
2 files changed +51
-6
lines changed Original file line number Diff line number Diff line change 5
5
createVNode ,
6
6
openBlock ,
7
7
createBlock ,
8
- Fragment
8
+ Fragment ,
9
+ createCommentVNode
9
10
} from '../../src'
10
11
import { PatchFlags } from '@vue/shared/src'
11
12
@@ -47,4 +48,31 @@ describe('renderSlot', () => {
47
48
const templateRendered = renderSlot ( { default : slot } , 'default' )
48
49
expect ( templateRendered . dynamicChildren ! . length ) . toBe ( 1 )
49
50
} )
51
+
52
+ // #2347 #2461
53
+ describe ( 'only render valid slot content' , ( ) => {
54
+ it ( 'should ignore slots that are all comments' , ( ) => {
55
+ let fallback
56
+ const vnode = renderSlot (
57
+ { default : ( ) => [ createCommentVNode ( 'foo' ) ] } ,
58
+ 'default' ,
59
+ undefined ,
60
+ ( ) => [ ( fallback = h ( 'fallback' ) ) ]
61
+ )
62
+ expect ( vnode . children ) . toEqual ( [ fallback ] )
63
+ expect ( vnode . patchFlag ) . toBe ( PatchFlags . BAIL )
64
+ } )
65
+
66
+ it ( 'should ignore invalid slot content generated by nested slot' , ( ) => {
67
+ let fallback
68
+ const vnode = renderSlot (
69
+ { default : ( ) => [ renderSlot ( { } , 'foo' ) ] } ,
70
+ 'default' ,
71
+ undefined ,
72
+ ( ) => [ ( fallback = h ( 'fallback' ) ) ]
73
+ )
74
+ expect ( vnode . children ) . toEqual ( [ fallback ] )
75
+ expect ( vnode . patchFlag ) . toBe ( PatchFlags . BAIL )
76
+ } )
77
+ } )
50
78
} )
Original file line number Diff line number Diff line change 1
1
import { Data } from '../component'
2
2
import { Slots , RawSlots } from '../componentSlots'
3
+ import { Comment , isVNode } from '../vnode'
3
4
import {
4
5
VNodeArrayChildren ,
5
6
openBlock ,
@@ -42,15 +43,31 @@ export function renderSlot(
42
43
// `renderSlot` we can be sure that it's template-based so we can force
43
44
// enable it.
44
45
isRenderingCompiledSlot ++
45
- const rendered = ( openBlock ( ) ,
46
- createBlock (
46
+ openBlock ( )
47
+ const validSlotContent = slot && ensureValidVNode ( slot ( props ) )
48
+ const rendered = createBlock (
47
49
Fragment ,
48
50
{ key : props . key } ,
49
- slot ? slot ( props ) : fallback ? fallback ( ) : [ ] ,
50
- ( slots as RawSlots ) . _ === SlotFlags . STABLE
51
+ validSlotContent || ( fallback ? fallback ( ) : [ ] ) ,
52
+ validSlotContent && ( slots as RawSlots ) . _ === SlotFlags . STABLE
51
53
? PatchFlags . STABLE_FRAGMENT
52
54
: PatchFlags . BAIL
53
- ) )
55
+ )
54
56
isRenderingCompiledSlot --
55
57
return rendered
56
58
}
59
+
60
+ function ensureValidVNode ( vnodes : VNodeArrayChildren ) {
61
+ return vnodes . some ( child => {
62
+ if ( ! isVNode ( child ) ) return true
63
+ if ( child . type === Comment ) return false
64
+ if (
65
+ child . type === Fragment &&
66
+ ! ensureValidVNode ( child . children as VNodeArrayChildren )
67
+ )
68
+ return false
69
+ return true
70
+ } )
71
+ ? vnodes
72
+ : null
73
+ }
You can’t perform that action at this time.
0 commit comments