text: /* @flow */
  
  import type VNode from 'core/vdom/vnode'
  
  /**
   * Runtime helper for resolving raw children VNodes into a slot object.
   */
  export function resolveSlots (
    children: ?Array<VNode>,
    context: ?Component
  ): { [key: string]: Array<VNode> } {
    const slots = {}
    if (!children) {
      return slots
    }
    for (let i = 0, l = children.length; i < l; i++) {
      const child = children[i]
      const data = child.data
      // remove slot attribute if the node is resolved as a Vue slot node
      //属性中的插槽和本身data里面的插槽不能同时存在
      if (data && data.attrs && data.attrs.slot) {
        delete data.attrs.slot
      }
      // named slots should only be respected if the vnode was rendered in the
      // same context.
      //根据name属性渲染的插槽必须在同一个上下文中
      if ((child.context === context || child.fnContext === context) &&
        data && data.slot != null
      ) {
        const name = data.slot
        const slot = (slots[name] || (slots[name] = []))
        //如果是template标签，多个child 的 push，插入到队列中
        if (child.tag === 'template') {
          slot.push.apply(slot, child.children || [])
        } else {
          //单个直接插入到队列中
          slot.push(child)
        }
      } else {
        //否则直接插入队列
        (slots.default || (slots.default = [])).push(child)
      }
    }
    // ignore slots that contains only whitespace
    //过滤空值
    for (const name in slots) {
      if (slots[name].every(isWhitespace)) {
        delete slots[name]
      }
    }
    return slots
  }
  
  function isWhitespace (node: VNode): boolean {
    return (node.isComment && !node.asyncFactory) || node.text === ' '
  }
  
  export function resolveScopedSlots (
    fns: ScopedSlotsData, // see flow/vnode
    res?: Object
  ): { [key: string]: Function } {
    res = res || {}
    for (let i = 0; i < fns.length; i++) {
      if (Array.isArray(fns[i])) {
        resolveScopedSlots(fns[i], res)
      } else {
        res[fns[i].key] = fns[i].fn
      }
    }
    return res
  }
  