]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: slots proxy
authorEvan You <evan@vuejs.org>
Fri, 6 Dec 2024 14:45:45 +0000 (22:45 +0800)
committerEvan You <evan@vuejs.org>
Fri, 6 Dec 2024 14:45:45 +0000 (22:45 +0800)
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/componentSlots.ts [new file with mode: 0644]

index 251ad75bace7e1e7efc99091b6b260d6c412930b..79f05c9cd68a51ab5747262e92f354219574a23d 100644 (file)
@@ -34,8 +34,8 @@ import { setStyle } from './dom/style'
 import { setClass, setDynamicProp } from './dom/prop'
 import {
   type RawSlots,
-  type Slot,
-  getSlotsProxyHandlers,
+  type StaticSlots,
+  slotsProxyHandlers,
 } from './componentSlots'
 
 export { currentInstance } from '@vue/runtime-dom'
@@ -178,7 +178,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
   rawProps: RawProps
   props: Record<string, any>
   attrs: Record<string, any>
-  slots: Record<string, Slot>
+  slots: StaticSlots
   exposed: Record<string, any> | null
 
   emitted: Record<string, boolean> | null
@@ -257,9 +257,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
     }
 
     // init slots
-    this.slots = rawSlots
-      ? new Proxy(rawSlots, getSlotsProxyHandlers(comp))
-      : EMPTY_OBJ
+    this.slots = rawSlots ? new Proxy(rawSlots, slotsProxyHandlers) : EMPTY_OBJ
 
     if (__DEV__) {
       // validate props
diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts
new file mode 100644 (file)
index 0000000..a77ade4
--- /dev/null
@@ -0,0 +1,74 @@
+import { NO, hasOwn, isArray, isFunction } from '@vue/shared'
+import type { Block } from './block'
+
+export type RawSlots = Record<string, Slot> & {
+  $?: (StaticSlots | DynamicSlotFn)[]
+}
+
+export type StaticSlots = Record<string, Slot>
+
+export type Slot = (...args: any[]) => Block
+export type DynamicSlot = { name: string; fn: Slot }
+export type DynamicSlotFn = () => DynamicSlot | DynamicSlot[]
+
+export const slotsProxyHandlers: ProxyHandler<RawSlots> = {
+  get: getSlot,
+  has: (target, key: string) => !!getSlot(target, key),
+  getOwnPropertyDescriptor(target, key: string) {
+    const slot = getSlot(target, key)
+    if (slot) {
+      return {
+        configurable: true,
+        enumerable: true,
+        value: slot,
+      }
+    }
+  },
+  ownKeys(target) {
+    const keys = Object.keys(target)
+    const dynamicSources = target.$
+    if (dynamicSources) {
+      for (const source of dynamicSources) {
+        if (isFunction(source)) {
+          const slot = source()
+          if (isArray(slot)) {
+            for (const s of slot) keys.push(s.name)
+          } else {
+            keys.push(slot.name)
+          }
+        } else {
+          keys.push(...Object.keys(source))
+        }
+      }
+    }
+    return keys
+  },
+  set: NO,
+  deleteProperty: NO,
+}
+
+function getSlot(target: RawSlots, key: string) {
+  const dynamicSources = target.$
+  if (dynamicSources) {
+    let i = dynamicSources.length
+    let source
+    while (i--) {
+      source = dynamicSources[i]
+      if (isFunction(source)) {
+        const slot = source()
+        if (isArray(slot)) {
+          for (const s of slot) {
+            if (s.name === key) return s.fn
+          }
+        } else if (slot.name === key) {
+          return slot.fn
+        }
+      } else if (hasOwn(source, key)) {
+        return source[key]
+      }
+    }
+  }
+  if (hasOwn(target, key)) {
+    return target[key]
+  }
+}