if (!currentInstance) {
// TODO warn
} else {
- const provides = currentInstance.provides || (currentInstance.provides = {})
+ let provides = currentInstance.provides
+ // by default an instance inherits its parent's provides object
+ // but when it needs to provide values of its own, it creates its
+ // own provides object using parent provides object as prototype.
+ // this way in `inject` we can simply look up injections from direct
+ // parent and let the prototype chain do the work.
+ const parentProvides =
+ currentInstance.parent && currentInstance.parent.provides
+ if (parentProvides === provides) {
+ provides = currentInstance.provides = Object.create(parentProvides)
+ }
provides[key as any] = value
}
}
export function inject<T>(key: Key<T>): Value<T> | undefined {
- // traverse parent chain and look for provided value
if (!currentInstance) {
// TODO warn
} else {
- let parent = currentInstance.parent
- while (parent) {
- const { provides } = parent
- if (provides !== null && provides.hasOwnProperty(key as any)) {
- const val = provides[key as any]
- return isValue(val) ? val : value(val)
- }
- parent = parent.parent
+ const provides = currentInstance.parent && currentInstance.provides
+ if (provides) {
+ const val = provides[key as any]
+ return isValue(val) ? val : value(val)
}
}
}
update: ReactiveEffect
render: RenderFunction<P, S> | null
effects: ReactiveEffect[] | null
- provides: Data | null
+ provides: Data
// the rest are only for stateful components
data: S
rtc: null,
ec: null,
effects: null,
- provides: null,
+ provides: parent ? parent.provides : {},
// public properties
data: EMPTY_OBJ,
// 2. call setup()
const { setup } = Component
if (setup) {
- currentInstance = instance
// the props proxy makes the props object passed to setup() reactive
// so props change can be tracked by watchers
// it will be updated in resolveProps() on updates before render
: null)
const setupContext = (instance.setupContext =
setup.length > 1 ? createSetupContext(instance) : null)
+
+ currentInstance = instance
const setupResult = setup.call(null, propsProxy, setupContext)
+ currentInstance = null
+
if (isFunction(setupResult)) {
// setup returned an inline render function
instance.render = setupResult
}
instance.render = Component.render as RenderFunction
}
- currentInstance = null
}
}