]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(slots): refine internal key checking to support slot names starting with an under...
authoredison <daiwei521@126.com>
Wed, 23 Jul 2025 00:40:20 +0000 (08:40 +0800)
committerGitHub <noreply@github.com>
Wed, 23 Jul 2025 00:40:20 +0000 (08:40 +0800)
close #13611

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

index ad87e5367d781e31fadd822cdaac3221c64636e2..765fce33e42765419509ddb675eb18df7fd7a1bc 100644 (file)
@@ -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')
+  })
 })
index 6114f6c86cf183ce83b49f433740f44deead40a2..380728750f84768600851eda8917ecdf835fecb8 100644 (file)
@@ -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)