fix(slots): refine internal key checking logic
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details

This commit is contained in:
daiwei 2025-07-10 22:34:44 +08:00
parent 347ef1d3f5
commit 4139e22385
2 changed files with 26 additions and 2 deletions

View File

@ -6,6 +6,7 @@ import {
nodeOps, nodeOps,
ref, ref,
render, render,
serializeInner,
useSlots, useSlots,
} from '@vue/runtime-test' } from '@vue/runtime-test'
import { createBlock, normalizeVNode } from '../src/vnode' import { createBlock, normalizeVNode } from '../src/vnode'
@ -74,6 +75,10 @@ describe('component: slots', () => {
footer: ['f1', 'f2'], footer: ['f1', 'f2'],
}) })
expect(
'[Vue warn]: Non-function value encountered for slot "_inner". Prefer function slots for better performance.',
).toHaveBeenWarned()
expect( expect(
'[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.', '[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.',
).toHaveBeenWarned() ).toHaveBeenWarned()
@ -82,8 +87,8 @@ describe('component: slots', () => {
'[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.', '[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.',
).toHaveBeenWarned() ).toHaveBeenWarned()
expect(slots).not.toHaveProperty('_inner')
expect(slots).not.toHaveProperty('foo') expect(slots).not.toHaveProperty('foo')
expect(slots._inner()).toMatchObject([normalizeVNode('_inner')])
expect(slots.header()).toMatchObject([normalizeVNode('header')]) expect(slots.header()).toMatchObject([normalizeVNode('header')])
expect(slots.footer()).toMatchObject([ expect(slots.footer()).toMatchObject([
normalizeVNode('f1'), normalizeVNode('f1'),
@ -442,4 +447,22 @@ describe('component: slots', () => {
'Slot "default" invoked outside of the render function', 'Slot "default" invoked outside of the render function',
).toHaveBeenWarned() ).toHaveBeenWarned()
}) })
test('slot name starts with underscore', () => {
const Comp = {
setup(_: any, { slots }: any) {
return () => slots._foo()
},
}
const App = {
setup() {
return () => h(Comp, null, { _foo: () => 'foo' })
},
}
const root = nodeOps.createElement('div')
createApp(App).mount(root)
expect(serializeInner(root)).toBe('foo')
})
}) })

View File

@ -86,7 +86,8 @@ export type RawSlots = {
__?: number[] __?: number[]
} }
const isInternalKey = (key: string) => key[0] === '_' || key === '$stable' const isInternalKey = (key: string) =>
key === '_' || key === '__' || key === '_ctx' || key === '$stable'
const normalizeSlotValue = (value: unknown): VNode[] => const normalizeSlotValue = (value: unknown): VNode[] =>
isArray(value) isArray(value)