import { warn, hasSymbol, isFunction, isObject } from '../util/index'
|
import { defineReactive, toggleObserving } from '../observer/index'
|
import type { Component } from 'types/component'
|
import { resolveProvided } from 'v3/apiInject'
|
|
export function initProvide(vm: Component) {
|
const provideOption = vm.$options.provide
|
if (provideOption) {
|
const provided = isFunction(provideOption)
|
? provideOption.call(vm)
|
: provideOption
|
if (!isObject(provided)) {
|
return
|
}
|
const source = resolveProvided(vm)
|
// IE9 doesn't support Object.getOwnPropertyDescriptors so we have to
|
// iterate the keys ourselves.
|
const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided)
|
for (let i = 0; i < keys.length; i++) {
|
const key = keys[i]
|
Object.defineProperty(
|
source,
|
key,
|
Object.getOwnPropertyDescriptor(provided, key)!
|
)
|
}
|
}
|
}
|
|
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 (__DEV__) {
|
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
|
): Record<string, any> | undefined | null {
|
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) : Object.keys(inject)
|
|
for (let i = 0; i < keys.length; i++) {
|
const key = keys[i]
|
// #6574 in case the inject object is observed...
|
if (key === '__ob__') continue
|
const provideKey = inject[key].from
|
if (provideKey in vm._provided) {
|
result[key] = vm._provided[provideKey]
|
} else if ('default' in inject[key]) {
|
const provideDefault = inject[key].default
|
result[key] = isFunction(provideDefault)
|
? provideDefault.call(vm)
|
: provideDefault
|
} else if (__DEV__) {
|
warn(`Injection "${key as string}" not found`, vm)
|
}
|
}
|
return result
|
}
|
}
|