import { setClass, setDynamicProp } from './dom/prop'
import {
type RawSlots,
- type Slot,
- getSlotsProxyHandlers,
+ type StaticSlots,
+ slotsProxyHandlers,
} from './componentSlots'
export { currentInstance } from '@vue/runtime-dom'
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
}
// 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
--- /dev/null
+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]
+ }
+}