Skip to content

Commit d76dd9c

Browse files
committedJul 12, 2024··
fix(runtime-core): force diff slot fallback content and provided content
fix #7256 fix #9200 fix #9308 close #7266 close #9213
1 parent 685e3f3 commit d76dd9c

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed
 

‎packages/runtime-core/__tests__/helpers/renderSlot.spec.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ describe('renderSlot', () => {
2626
const vnode = renderSlot(
2727
{ default: () => [(child = h('child'))] },
2828
'default',
29+
{ key: 'foo' },
2930
)
3031
expect(vnode.children).toEqual([child])
32+
expect(vnode.key).toBe('foo')
3133
})
3234

3335
it('should render slot fallback', () => {
34-
const vnode = renderSlot({}, 'default', {}, () => ['fallback'])
36+
const vnode = renderSlot({}, 'default', { key: 'foo' }, () => ['fallback'])
3537
expect(vnode.children).toEqual(['fallback'])
38+
// should attach fallback key postfix
39+
expect(vnode.key).toBe('foo_fb')
3640
})
3741

3842
it('should warn render ssr slot', () => {

‎packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts

+73
Original file line numberDiff line numberDiff line change
@@ -1105,4 +1105,77 @@ describe('renderer: optimized mode', () => {
11051105
expect(app.config.errorHandler).not.toHaveBeenCalled()
11061106
}
11071107
})
1108+
1109+
test('diff slot and slot fallback node', async () => {
1110+
const Comp = {
1111+
props: ['show'],
1112+
setup(props: any, { slots }: SetupContext) {
1113+
return () => {
1114+
return (
1115+
openBlock(),
1116+
createElementBlock('div', null, [
1117+
renderSlot(slots, 'default', { hide: !props.show }, () => [
1118+
(openBlock(),
1119+
(block = createElementBlock(
1120+
Fragment,
1121+
{ key: 0 },
1122+
[createTextVNode('foo')],
1123+
PatchFlags.STABLE_FRAGMENT,
1124+
))),
1125+
]),
1126+
])
1127+
)
1128+
}
1129+
},
1130+
}
1131+
1132+
const show = ref(true)
1133+
const app = createApp({
1134+
render() {
1135+
return (
1136+
openBlock(),
1137+
createBlock(
1138+
Comp,
1139+
{ show: show.value },
1140+
{
1141+
default: withCtx(({ hide }: { hide: boolean }) => [
1142+
!hide
1143+
? (openBlock(),
1144+
createElementBlock(
1145+
Fragment,
1146+
{ key: 0 },
1147+
[
1148+
createCommentVNode('comment'),
1149+
createElementVNode(
1150+
'div',
1151+
null,
1152+
'bar',
1153+
PatchFlags.HOISTED,
1154+
),
1155+
],
1156+
PatchFlags.STABLE_FRAGMENT,
1157+
))
1158+
: createCommentVNode('v-if', true),
1159+
]),
1160+
_: SlotFlags.STABLE,
1161+
},
1162+
PatchFlags.PROPS,
1163+
['show'],
1164+
)
1165+
)
1166+
},
1167+
})
1168+
1169+
app.mount(root)
1170+
expect(inner(root)).toBe('<div><!--comment--><div>bar</div></div>')
1171+
expect(block).toBe(null)
1172+
1173+
show.value = false
1174+
await nextTick()
1175+
expect(inner(root)).toBe('<div>foo</div>')
1176+
1177+
show.value = true
1178+
await nextTick()
1179+
expect(inner(root)).toBe('<div><!--comment--><div>bar</div></div>')
1180+
})
11081181
})

‎packages/runtime-core/src/helpers/renderSlot.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ export function renderSlot(
6565
Fragment,
6666
{
6767
key:
68-
props.key ||
69-
// slot content array of a dynamic conditional slot may have a branch
70-
// key attached in the `createSlots` helper, respect that
71-
(validSlotContent && (validSlotContent as any).key) ||
72-
`_${name}`,
68+
(props.key ||
69+
// slot content array of a dynamic conditional slot may have a branch
70+
// key attached in the `createSlots` helper, respect that
71+
(validSlotContent && (validSlotContent as any).key) ||
72+
`_${name}`) +
73+
// #7256 force differentiate fallback content from actual content
74+
(!validSlotContent && fallback ? '_fb' : ''),
7375
},
7476
validSlotContent || (fallback ? fallback() : []),
7577
validSlotContent && (slots as RawSlots)._ === SlotFlags.STABLE

0 commit comments

Comments
 (0)
Please sign in to comment.