From 4ce0df6ef1a31ee45402e61e01777e3836b2c223 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Tue, 25 May 2021 06:17:37 +0800 Subject: [PATCH] fix(runtime-core): avoid the proxy object polluting the slots of the internal instance (#3698) fix #3695 --- packages/runtime-core/src/componentRenderContext.ts | 3 ++- packages/runtime-core/src/componentSlots.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/componentRenderContext.ts b/packages/runtime-core/src/componentRenderContext.ts index 18dcd6f2f8..a25756864e 100644 --- a/packages/runtime-core/src/componentRenderContext.ts +++ b/packages/runtime-core/src/componentRenderContext.ts @@ -89,7 +89,8 @@ export function withCtx( // mark this as a compiled slot function. // this is used in vnode.ts -> normalizeChildren() to set the slot // rendering flag. - renderFnWithContext._c = true + // also used to cache the normalized results to avoid repeated normalization + renderFnWithContext._c = renderFnWithContext if (__COMPAT__ && isNonScopedSlot) { renderFnWithContext._nonScoped = true } diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index 9fdb0d142d..7e0fe3cb61 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -20,6 +20,7 @@ import { isKeepAlive } from './components/KeepAlive' import { withCtx } from './componentRenderContext' import { isHmrUpdating } from './hmr' import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig' +import { toRaw } from '@vue/reactivity' export type Slot = (...args: any[]) => VNode[] @@ -62,7 +63,8 @@ const normalizeSlot = ( rawSlot: Function, ctx: ComponentInternalInstance | null | undefined ): Slot => - withCtx((props: any) => { + (rawSlot as any)._c || + (withCtx((props: any) => { if (__DEV__ && currentInstance) { warn( `Slot "${key}" invoked outside of the render function: ` + @@ -71,7 +73,7 @@ const normalizeSlot = ( ) } return normalizeSlotValue(rawSlot(props)) - }, ctx) as Slot + }, ctx) as Slot) const normalizeObjectSlots = ( rawSlots: RawSlots, @@ -128,7 +130,9 @@ export const initSlots = ( if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { const type = (children as RawSlots)._ if (type) { - instance.slots = children as InternalSlots + // users can get the shallow readonly version of the slots object through `this.$slots`, + // we should avoid the proxy object polluting the slots of the internal instance + instance.slots = toRaw(children as InternalSlots) // make compiler marker non-enumerable def(children as InternalSlots, '_', type) } else { -- 2.47.3