text: /* @flow */
  
  import config from '../config'
  import { initProxy } from './proxy'
  import { initState } from './state'
  import { initRender } from './render'
  import { initEvents } from './events'
  import { mark, measure } from '../util/perf'
  import { initLifecycle, callHook } from './lifecycle'
  import { initProvide, initInjections } from './inject'
  import { extend, mergeOptions, formatComponentName } from '../util/index'
  
  let uid = 0
  
  /**
   * 定义 Vue.prototype._init
   * @param {*} Vue Vue 构造函数
   */
  export function initMixin (Vue: Class<Component>) {
    // 负责 Vue 的初始化过程
    Vue.prototype._init = function (options?: Object) {
      // vue 实例
      const vm: Component = this
      // 每个 vue 实例都有一个 _uid，并且是依次递增的
      vm._uid = uid++
  
      let startTag, endTag
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        startTag = `vue-perf-start:${vm._uid}`
        endTag = `vue-perf-end:${vm._uid}`
        mark(startTag)
      }
  
      // a flag to avoid this being observed
      vm._isVue = true
      // 处理组件配置项
      if (options && options._isComponent) {
        /**
         * 每个子组件初始化时走这里，这里只做了性能优化，将组件配置对象上的一些深层次属性放到 vm.$options 选项中，以提高代码执行效率
         * 至于每个子组件的选项合并发生在两个地方：
         *   1、Vue.component 方法注册的全局组件在注册时做了选项合并
         *   2、{ components: { xxx } } 方式注册的局部组件在执行编译器生成的 render 函数时做了选项合并，包括根组件中的 components 配置
         */
        initInternalComponent(vm, options)
      } else {
        // 初始化根组件时走这里，合并 Vue 的全局配置到根组件的局部配置，比如 Vue.component 注册的全局组件最后会合并到 根组件实例的 components 选项中
        vm.$options = mergeOptions(
          resolveConstructorOptions(vm.constructor),
          options || {},
          vm
        )
      }
      /* istanbul ignore else */
      if (process.env.NODE_ENV !== 'production') {
        // 设置代理，将 vm 实例上的属性代理到 vm._renderProxy
        initProxy(vm)
      } else {
        vm._renderProxy = vm
      }
      // expose real self
      vm._self = vm
      // 初始化组件实例关系属性，比如 $parent、$children、$root、$refs 等
      initLifecycle(vm)
      /**
       * 初始化自定义事件，这里需要注意一点，所以我们在 <comp @click="handleClick" /> 上注册的事件，监听者不是父组件，
       * 而是子组件本身，也就是说事件的派发和监听者都是子组件本身，和父组件无关
       */
      initEvents(vm)
      // 解析组件的插槽信息，得到 vm.$slot，处理渲染函数，得到 vm.$createElement 方法，即 h 函数
      initRender(vm)
      // 调用 beforeCreate 钩子函数
      callHook(vm, 'beforeCreate')
      // 初始化组件的 inject 配置项，得到 result[key] = val 形式的配置对象，然后对结果数据进行浅层的响应式处理（只处理了对象的第一层数据），并代理每个 key 到 vm 实例
      initInjections(vm) // resolve injections before data/props
      // 数据响应式的重点，处理 props、methods、data、computed、watch
      initState(vm)
      // 解析组件配置项上的 provide 对象，将其挂载到 vm._provided 属性上 
      initProvide(vm) // resolve provide after data/props
      // 调用 created 钩子函数
      callHook(vm, 'created')
  
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        vm._name = formatComponentName(vm, false)
        mark(endTag)
        measure(`vue ${vm._name} init`, startTag, endTag)
      }
  
      // 如果发现配置项上有 el 选项，则自动调用 $mount 方法，也就是说有了 el 选项，就不需要再手动调用 $mount，反之，没有 el 则必须手动调用 $mount
      if (vm.$options.el) {
        // 调用 $mount 方法，进入挂载阶段
        vm.$mount(vm.$options.el)
      }
    }
  }
  
  export function initInternalComponent (vm: Component, options: InternalComponentOptions) {
    const opts = vm.$options = Object.create(vm.constructor.options)
    // doing this because it's faster than dynamic enumeration.
    const parentVnode = options._parentVnode
    opts.parent = options.parent
    opts._parentVnode = parentVnode
  
    const vnodeComponentOptions = parentVnode.componentOptions
    opts.propsData = vnodeComponentOptions.propsData
    opts._parentListeners = vnodeComponentOptions.listeners
    opts._renderChildren = vnodeComponentOptions.children
    opts._componentTag = vnodeComponentOptions.tag
  
    if (options.render) {
      opts.render = options.render
      opts.staticRenderFns = options.staticRenderFns
    }
  }
  
  /**
   * 从构造函数上解析配置项
   */
  export function resolveConstructorOptions (Ctor: Class<Component>) {
    // 从实例构造函数上获取选项
    let options = Ctor.options
    if (Ctor.super) {
      const superOptions = resolveConstructorOptions(Ctor.super)
      // 缓存
      const cachedSuperOptions = Ctor.superOptions
      if (superOptions !== cachedSuperOptions) {
        // 说明基类的配置项发生了更改
        // super option changed,
        // need to resolve new options.
        Ctor.superOptions = superOptions
        // check if there are any late-modified/attached options (#4976)
        // 找到更改的选项
        const modifiedOptions = resolveModifiedOptions(Ctor)
        // update base extend options
        if (modifiedOptions) {
          // 将更改的选项和 extend 选项合并
          extend(Ctor.extendOptions, modifiedOptions)
        }
        // 将新的选项赋值给 options
        options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
        if (options.name) {
          options.components[options.name] = Ctor
        }
      }
    }
    return options
  }
  
  /**
   * 解析构造函数选项中后续被修改或者增加的选项
   */
  function resolveModifiedOptions (Ctor: Class<Component>): ?Object {
    let modified
    // 构造函数选项
    const latest = Ctor.options
    // 密封的构造函数选项，备份
    const sealed = Ctor.sealedOptions
    // 对比两个选项，记录不一致的选项
    for (const key in latest) {
      if (latest[key] !== sealed[key]) {
        if (!modified) modified = {}
        modified[key] = latest[key]
      }
    }
    return modified
  }
  