Skip to content

Commit 4ce0df6

Browse files
authored
fix(runtime-core): avoid the proxy object polluting the slots of the internal instance (#3698)
fix #3695
1 parent 7c74feb commit 4ce0df6

File tree

2 files changed

+9
-4
lines changed

2 files changed

+9
-4
lines changed

packages/runtime-core/src/componentRenderContext.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ export function withCtx(
8989
// mark this as a compiled slot function.
9090
// this is used in vnode.ts -> normalizeChildren() to set the slot
9191
// rendering flag.
92-
renderFnWithContext._c = true
92+
// also used to cache the normalized results to avoid repeated normalization
93+
renderFnWithContext._c = renderFnWithContext
9394
if (__COMPAT__ && isNonScopedSlot) {
9495
renderFnWithContext._nonScoped = true
9596
}

packages/runtime-core/src/componentSlots.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { isKeepAlive } from './components/KeepAlive'
2020
import { withCtx } from './componentRenderContext'
2121
import { isHmrUpdating } from './hmr'
2222
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
23+
import { toRaw } from '@vue/reactivity'
2324

2425
export type Slot = (...args: any[]) => VNode[]
2526

@@ -62,7 +63,8 @@ const normalizeSlot = (
6263
rawSlot: Function,
6364
ctx: ComponentInternalInstance | null | undefined
6465
): Slot =>
65-
withCtx((props: any) => {
66+
(rawSlot as any)._c ||
67+
(withCtx((props: any) => {
6668
if (__DEV__ && currentInstance) {
6769
warn(
6870
`Slot "${key}" invoked outside of the render function: ` +
@@ -71,7 +73,7 @@ const normalizeSlot = (
7173
)
7274
}
7375
return normalizeSlotValue(rawSlot(props))
74-
}, ctx) as Slot
76+
}, ctx) as Slot)
7577

7678
const normalizeObjectSlots = (
7779
rawSlots: RawSlots,
@@ -128,7 +130,9 @@ export const initSlots = (
128130
if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
129131
const type = (children as RawSlots)._
130132
if (type) {
131-
instance.slots = children as InternalSlots
133+
// users can get the shallow readonly version of the slots object through `this.$slots`,
134+
// we should avoid the proxy object polluting the slots of the internal instance
135+
instance.slots = toRaw(children as InternalSlots)
132136
// make compiler marker non-enumerable
133137
def(children as InternalSlots, '_', type)
134138
} else {

0 commit comments

Comments
 (0)