Sfoglia il codice sorgente

fix(slots): make cache indexes marker non-enumerable (#13469)

close #13468
edison 10 mesi fa
parent
commit
919c44744b

+ 24 - 0
packages/runtime-core/__tests__/componentSlots.spec.ts

@@ -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',

+ 4 - 0
packages/runtime-core/src/componentSlots.ts

@@ -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)