Skip to content

Commit 6c90324

Browse files
authored
fix(ssr): ensure content is valid when rendering normal slot (#11491)
fix #11326
1 parent fdc2a31 commit 6c90324

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function renderSlot(
8787
return rendered
8888
}
8989

90-
function ensureValidVNode(vnodes: VNodeArrayChildren) {
90+
export function ensureValidVNode(vnodes: VNodeArrayChildren) {
9191
return vnodes.some(child => {
9292
if (!isVNode(child)) return true
9393
if (child.type === Comment) return false

packages/runtime-core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ import {
371371
import { renderComponentRoot } from './componentRenderUtils'
372372
import { setCurrentRenderingInstance } from './componentRenderContext'
373373
import { isVNode, normalizeVNode } from './vnode'
374+
import { ensureValidVNode } from './helpers/renderSlot'
374375

375376
const _ssrUtils = {
376377
createComponentInstance,
@@ -380,6 +381,7 @@ const _ssrUtils = {
380381
isVNode,
381382
normalizeVNode,
382383
getComponentPublicInstance,
384+
ensureValidVNode,
383385
}
384386

385387
/**

packages/server-renderer/__tests__/ssrSlot.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,54 @@ describe('ssr: slot', () => {
153153
),
154154
).toBe(`<div><p>1</p><p>2</p></div>`)
155155
})
156+
157+
// #11326
158+
test('dynamic component slot', async () => {
159+
expect(
160+
await renderToString(
161+
createApp({
162+
components: {
163+
ButtonComp: {
164+
template: `<component is="button"><slot/></component>`,
165+
},
166+
Wrap: {
167+
template: `<div><slot/></div>`,
168+
},
169+
},
170+
template: `<ButtonComp><Wrap><div v-if="false">hello</div></Wrap></ButtonComp>`,
171+
}),
172+
),
173+
).toBe(`<button><!--[--><div><!--[--><!--]--></div><!--]--></button>`)
174+
175+
expect(
176+
await renderToString(
177+
createApp({
178+
components: {
179+
ButtonComp: {
180+
template: `<component is="button"><slot/></component>`,
181+
},
182+
Wrap: {
183+
template: `<div><slot/></div>`,
184+
},
185+
},
186+
template: `<ButtonComp><Wrap><div v-if="true">hello</div></Wrap></ButtonComp>`,
187+
}),
188+
),
189+
).toBe(
190+
`<button><!--[--><div><!--[--><div>hello</div><!--]--></div><!--]--></button>`,
191+
)
192+
193+
expect(
194+
await renderToString(
195+
createApp({
196+
components: {
197+
ButtonComp: {
198+
template: `<component is="button"><slot/></component>`,
199+
},
200+
},
201+
template: `<ButtonComp><template v-if="false">hello</template></ButtonComp>`,
202+
}),
203+
),
204+
).toBe(`<button><!--[--><!--]--></button>`)
205+
})
156206
})

packages/server-renderer/src/helpers/ssrRenderSlot.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ComponentInternalInstance, Slots } from 'vue'
1+
import { type ComponentInternalInstance, type Slots, ssrUtils } from 'vue'
22
import {
33
type Props,
44
type PushFn,
@@ -7,6 +7,8 @@ import {
77
} from '../render'
88
import { isArray } from '@vue/shared'
99

10+
const { ensureValidVNode } = ssrUtils
11+
1012
export type SSRSlots = Record<string, SSRSlot>
1113
export type SSRSlot = (
1214
props: Props,
@@ -61,8 +63,18 @@ export function ssrRenderSlotInner(
6163
slotScopeId ? ' ' + slotScopeId : '',
6264
)
6365
if (isArray(ret)) {
64-
// normal slot
65-
renderVNodeChildren(push, ret, parentComponent, slotScopeId)
66+
const validSlotContent = ensureValidVNode(ret)
67+
if (validSlotContent) {
68+
// normal slot
69+
renderVNodeChildren(
70+
push,
71+
validSlotContent,
72+
parentComponent,
73+
slotScopeId,
74+
)
75+
} else if (fallbackRenderFn) {
76+
fallbackRenderFn()
77+
}
6678
} else {
6779
// ssr slot.
6880
// check if the slot renders all comments, in which case use the fallback

0 commit comments

Comments
 (0)