From: edison Date: Wed, 23 Jul 2025 00:40:20 +0000 (+0800) Subject: fix(slots): refine internal key checking to support slot names starting with an under... X-Git-Tag: v3.5.18~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c5f7db11542bb2246363aef78c88a8e6cef0ee93;p=thirdparty%2Fvuejs%2Fcore.git fix(slots): refine internal key checking to support slot names starting with an underscore (#13612) close #13611 --- diff --git a/packages/runtime-core/__tests__/componentSlots.spec.ts b/packages/runtime-core/__tests__/componentSlots.spec.ts index ad87e5367d..765fce33e4 100644 --- a/packages/runtime-core/__tests__/componentSlots.spec.ts +++ b/packages/runtime-core/__tests__/componentSlots.spec.ts @@ -6,6 +6,7 @@ import { nodeOps, ref, render, + serializeInner, useSlots, } from '@vue/runtime-test' import { createBlock, normalizeVNode } from '../src/vnode' @@ -74,6 +75,10 @@ describe('component: slots', () => { footer: ['f1', 'f2'], }) + expect( + '[Vue warn]: Non-function value encountered for slot "_inner". Prefer function slots for better performance.', + ).toHaveBeenWarned() + expect( '[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.', ).toHaveBeenWarned() @@ -82,8 +87,8 @@ describe('component: slots', () => { '[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.', ).toHaveBeenWarned() - expect(slots).not.toHaveProperty('_inner') expect(slots).not.toHaveProperty('foo') + expect(slots._inner()).toMatchObject([normalizeVNode('_inner')]) expect(slots.header()).toMatchObject([normalizeVNode('header')]) expect(slots.footer()).toMatchObject([ normalizeVNode('f1'), @@ -442,4 +447,22 @@ describe('component: slots', () => { 'Slot "default" invoked outside of the render function', ).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') + }) }) diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index 6114f6c86c..380728750f 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -86,7 +86,8 @@ export type RawSlots = { __?: number[] } -const isInternalKey = (key: string) => key[0] === '_' || key === '$stable' +const isInternalKey = (key: string) => + key === '_' || key === '__' || key === '_ctx' || key === '$stable' const normalizeSlotValue = (value: unknown): VNode[] => isArray(value)