]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(slots): make cache indexes marker non-enumerable (#13469)
authoredison <daiwei521@126.com>
Wed, 18 Jun 2025 12:53:48 +0000 (20:53 +0800)
committerGitHub <noreply@github.com>
Wed, 18 Jun 2025 12:53:48 +0000 (20:53 +0800)
close #13468

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

index 2cf50b964bf5523184e8ed7a5bc7cc773f807441..ad87e5367d781e31fadd822cdaac3221c64636e2 100644 (file)
@@ -6,6 +6,7 @@ import {
   nodeOps,
   ref,
   render,
+  useSlots,
 } from '@vue/runtime-test'
 import { createBlock, normalizeVNode } from '../src/vnode'
 import { createSlots } from '../src/helpers/createSlots'
@@ -42,6 +43,29 @@ describe('component: slots', () => {
     expect(slots).toMatchObject({})
   })
 
+  test('initSlots: ensure compiler marker non-enumerable', () => {
+    const Comp = {
+      render() {
+        const slots = useSlots()
+        // Only user-defined slots should be enumerable
+        expect(Object.keys(slots)).toEqual(['foo'])
+
+        // Internal compiler markers must still exist but be non-enumerable
+        expect(slots).toHaveProperty('_')
+        expect(Object.getOwnPropertyDescriptor(slots, '_')!.enumerable).toBe(
+          false,
+        )
+        expect(slots).toHaveProperty('__')
+        expect(Object.getOwnPropertyDescriptor(slots, '__')!.enumerable).toBe(
+          false,
+        )
+        return h('div')
+      },
+    }
+    const slots = { foo: () => {}, _: 1, __: [1] }
+    render(createBlock(Comp, null, slots), nodeOps.createElement('div'))
+  })
+
   test('initSlots: should normalize object slots (when value is null, string, array)', () => {
     const { slots } = renderWithSlots({
       _inner: '_inner',
index 3812695431e53835fa25d731e89d8bd8629e4f75..6114f6c86cf183ce83b49f433740f44deead40a2 100644 (file)
@@ -193,6 +193,10 @@ export const initSlots = (
 ): void => {
   const slots = (instance.slots = createInternalObject())
   if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
+    const cacheIndexes = (children as RawSlots).__
+    // make cache indexes marker non-enumerable
+    if (cacheIndexes) def(slots, '__', cacheIndexes, true)
+
     const type = (children as RawSlots)._
     if (type) {
       assignSlots(slots, children as Slots, optimized)