import { ComponentInstance } from './component' import { VNode, NormalizedChildren, normalizeVNode, VNodeChild } from './vnode' import { isArray, isObject, isFunction } from '@vue/shared' export type Slot = (...args: any[]) => VNode[] export type Slots = Readonly<{ [name: string]: Slot }> export type RawSlots = { [name: string]: unknown } const normalizeSlotValue = (value: unknown): VNode[] => isArray(value) ? value.map(normalizeVNode) : [normalizeVNode(value as VNodeChild)] const normalizeSlot = (rawSlot: Function): Slot => (props: any) => normalizeSlotValue(rawSlot(props)) export function resolveSlots( instance: ComponentInstance, children: NormalizedChildren ) { let slots: Slots | void if (isObject(children) && !isArray(children)) { // pre-normalized slots object generated by compiler if ((children as any)._normalized) { slots = children as Slots } else { slots = {} for (const key in children) { let value = children[key] if (isFunction(value)) { ;(slots as any)[key] = normalizeSlot(value) } else { if (__DEV__) { // TODO show tip on using functions console.log('use function slots!') } value = normalizeSlotValue(value) ;(slots as any)[key] = () => value } } } } else if (children != null) { // Array, string or null. // non object children passed to a component if (__DEV__) { // TODO show tip on using functions console.log('use function slots!') } const normalized = normalizeSlotValue(children) slots = { default: () => normalized } } if (slots !== void 0) { instance.slots = slots } }