text: /* @flow */
  
  import { hasOwn } from 'shared/util'
  import { warn, hasSymbol } from '../util/index'
  import { defineReactive, toggleObserving } from '../observer/index'
  
  export function initProvide (vm: Component) {
    const provide = vm.$options.provide
    if (provide) {
      vm._provided = typeof provide === 'function'
        ? provide.call(vm)
        : provide
    }
  }
  
  export function initInjections (vm: Component) {
    const result = resolveInject(vm.$options.inject, vm)
    if (result) {
      toggleObserving(false)
      Object.keys(result).forEach(key => {
        /* istanbul ignore else */
        if (process.env.NODE_ENV !== 'production') {
          defineReactive(vm, key, result[key], () => {
            warn(
              `Avoid mutating an injected value directly since the changes will be ` +
              `overwritten whenever the provided component re-renders. ` +
              `injection being mutated: "${key}"`,
              vm
            )
          })
        } else {
          defineReactive(vm, key, result[key])
        }
      })
      toggleObserving(true)
    }
  }
  
  export function resolveInject (inject: any, vm: Component): ?Object {
    if (inject) {
      // inject is :any because flow is not smart enough to figure out cached
      const result = Object.create(null)
      const keys = hasSymbol
        ? Reflect.ownKeys(inject).filter(key => {
          /* istanbul ignore next */
          return Object.getOwnPropertyDescriptor(inject, key).enumerable
        })
        : Object.keys(inject)
  
      for (let i = 0; i < keys.length; i++) {
        const key = keys[i]
        const provideKey = inject[key].from
        let source = vm
        while (source) {
          if (source._provided && hasOwn(source._provided, provideKey)) {
            result[key] = source._provided[provideKey]
            break
          }
          source = source.$parent
        }
        if (!source) {
          if ('default' in inject[key]) {
            const provideDefault = inject[key].default
            result[key] = typeof provideDefault === 'function'
              ? provideDefault.call(vm)
              : provideDefault
          } else if (process.env.NODE_ENV !== 'production') {
            warn(`Injection "${key}" not found`, vm)
          }
        }
      }
      return result
    }
  }
  