Skip to content

Commit 9196222

Browse files
fix(slots): properly warn if slot invoked in setup (#12195)
close #12194
1 parent 2206cd2 commit 9196222

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

packages/runtime-core/__tests__/componentSlots.spec.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,98 @@ describe('component: slots', () => {
324324
'Slot "default" invoked outside of the render function',
325325
).not.toHaveBeenWarned()
326326
})
327+
328+
test('basic warn', () => {
329+
const Comp = {
330+
setup(_: any, { slots }: any) {
331+
slots.default && slots.default()
332+
return () => null
333+
},
334+
}
335+
336+
const App = {
337+
setup() {
338+
return () => h(Comp, () => h('div'))
339+
},
340+
}
341+
342+
createApp(App).mount(nodeOps.createElement('div'))
343+
expect(
344+
'Slot "default" invoked outside of the render function',
345+
).toHaveBeenWarned()
346+
})
347+
348+
test('basic warn when mounting another app in setup', () => {
349+
const Comp = {
350+
setup(_: any, { slots }: any) {
351+
slots.default?.()
352+
return () => null
353+
},
354+
}
355+
356+
const mountComp = () => {
357+
createApp({
358+
setup() {
359+
return () => h(Comp, () => 'msg')
360+
},
361+
}).mount(nodeOps.createElement('div'))
362+
}
363+
364+
const App = {
365+
setup() {
366+
mountComp()
367+
return () => null
368+
},
369+
}
370+
371+
createApp(App).mount(nodeOps.createElement('div'))
372+
expect(
373+
'Slot "default" invoked outside of the render function',
374+
).toHaveBeenWarned()
375+
})
376+
377+
test('should not warn when render in setup', () => {
378+
const container = {
379+
setup(_: any, { slots }: any) {
380+
return () => slots.default && slots.default()
381+
},
382+
}
383+
384+
const comp = h(container, null, () => h('div'))
385+
386+
const App = {
387+
setup() {
388+
render(h(comp), nodeOps.createElement('div'))
389+
return () => null
390+
},
391+
}
392+
393+
createApp(App).mount(nodeOps.createElement('div'))
394+
expect(
395+
'Slot "default" invoked outside of the render function',
396+
).not.toHaveBeenWarned()
397+
})
398+
399+
test('basic warn when render in setup', () => {
400+
const container = {
401+
setup(_: any, { slots }: any) {
402+
slots.default && slots.default()
403+
return () => null
404+
},
405+
}
406+
407+
const comp = h(container, null, () => h('div'))
408+
409+
const App = {
410+
setup() {
411+
render(h(comp), nodeOps.createElement('div'))
412+
return () => null
413+
},
414+
}
415+
416+
createApp(App).mount(nodeOps.createElement('div'))
417+
expect(
418+
'Slot "default" invoked outside of the render function',
419+
).toHaveBeenWarned()
420+
})
327421
})

packages/runtime-core/src/componentSlots.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import {
1717
} from '@vue/shared'
1818
import { warn } from './warning'
1919
import { isKeepAlive } from './components/KeepAlive'
20-
import { type ContextualRenderFn, withCtx } from './componentRenderContext'
20+
import {
21+
type ContextualRenderFn,
22+
currentRenderingInstance,
23+
withCtx,
24+
} from './componentRenderContext'
2125
import { isHmrUpdating } from './hmr'
2226
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
2327
import { TriggerOpTypes, trigger } from '@vue/reactivity'
@@ -102,7 +106,8 @@ const normalizeSlot = (
102106
if (
103107
__DEV__ &&
104108
currentInstance &&
105-
(!ctx || ctx.root === currentInstance.root)
109+
!(ctx === null && currentRenderingInstance) &&
110+
!(ctx && ctx.root !== currentInstance.root)
106111
) {
107112
warn(
108113
`Slot "${key}" invoked outside of the render function: ` +

0 commit comments

Comments
 (0)