From 117630fb926e6cbd5a5efad7c377397fee532597 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 19 Jun 2019 22:48:22 +0800 Subject: [PATCH] perf: improve inject performance --- packages/runtime-core/src/apiInject.ts | 25 +++++++++++++++---------- packages/runtime-core/src/component.ts | 10 ++++++---- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/runtime-core/src/apiInject.ts b/packages/runtime-core/src/apiInject.ts index 7c9e64eac..3e266b36e 100644 --- a/packages/runtime-core/src/apiInject.ts +++ b/packages/runtime-core/src/apiInject.ts @@ -7,24 +7,29 @@ export function provide(key: Key, value: T | Value) { 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(key: Key): Value | 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) } } } diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 35886d68d..35c21568c 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -112,7 +112,7 @@ export type ComponentInstance

= { update: ReactiveEffect render: RenderFunction | null effects: ReactiveEffect[] | null - provides: Data | null + provides: Data // the rest are only for stateful components data: S @@ -194,7 +194,7 @@ export function createComponentInstance( rtc: null, ec: null, effects: null, - provides: null, + provides: parent ? parent.provides : {}, // public properties data: EMPTY_OBJ, @@ -225,7 +225,6 @@ export function setupStatefulComponent(instance: ComponentInstance) { // 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 @@ -234,7 +233,11 @@ export function setupStatefulComponent(instance: ComponentInstance) { : 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 @@ -247,7 +250,6 @@ export function setupStatefulComponent(instance: ComponentInstance) { } instance.render = Component.render as RenderFunction } - currentInstance = null } }