]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): avoid the proxy object polluting the slots of the internal instanc...
authorHcySunYang <HcySunYang@outlook.com>
Mon, 24 May 2021 22:17:37 +0000 (06:17 +0800)
committerGitHub <noreply@github.com>
Mon, 24 May 2021 22:17:37 +0000 (18:17 -0400)
fix #3695

packages/runtime-core/src/componentRenderContext.ts
packages/runtime-core/src/componentSlots.ts

index 18dcd6f2f88993018ba734dbe97557ae94057f10..a25756864e9c7dd252bb7543ee62061623200da2 100644 (file)
@@ -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
   }
index 9fdb0d142dbc9afeec6e74d97d975b6c47e2e68a..7e0fe3cb61b77381d80a4a9a90538a96f5901898 100644 (file)
@@ -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 {