From 51d2be20386d4dc59006d31a1cc96676871027ce Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 2 Jun 2021 15:22:52 -0400 Subject: [PATCH] perf: avoid deopt for props/emits normalization when global mixins are used --- packages/runtime-core/src/apiCreateApp.ts | 27 +++++++++++-------- packages/runtime-core/src/component.ts | 8 ------ packages/runtime-core/src/componentEmits.ts | 13 ++++++--- packages/runtime-core/src/componentOptions.ts | 2 +- packages/runtime-core/src/componentProps.ts | 13 ++++++--- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index 617ddd20..4bdc21c1 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -20,6 +20,8 @@ import { devtoolsInitApp, devtoolsUnmountApp } from './devtools' import { isFunction, NO, isObject } from '@vue/shared' import { version } from '.' import { installAppCompatProperties } from './compat/global' +import { NormalizedPropsOptions } from './componentProps' +import { ObjectEmitsOptions } from './componentEmits' export interface App { version: string @@ -101,13 +103,19 @@ export interface AppContext { * Cache for merged/normalized component options * Each app instance has its own cache because app-level global mixins and * optionMergeStrategies can affect merge behavior. - */ - cache: WeakMap - /** - * Flag for de-optimizing props normalization * @internal */ - deopt?: boolean + optionsCache: WeakMap + /** + * Cache for normalized props options + * @internal + */ + propsCache: WeakMap + /** + * Cache for normalized emits options + * @internal + */ + emitsCache: WeakMap /** * HMR only * @internal @@ -144,7 +152,9 @@ export function createAppContext(): AppContext { components: {}, directives: {}, provides: Object.create(null), - cache: new WeakMap() + optionsCache: new WeakMap(), + propsCache: new WeakMap(), + emitsCache: new WeakMap() } } @@ -213,11 +223,6 @@ export function createAppAPI( if (__FEATURE_OPTIONS_API__) { if (!context.mixins.includes(mixin)) { context.mixins.push(mixin) - // global mixin with props/emits de-optimizes props/emits - // normalization caching. - if (mixin.props || mixin.emits) { - context.deopt = true - } } else if (__DEV__) { warn( 'Mixin has already been applied to target app' + diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index fd7b5777..78cabdd3 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -76,14 +76,6 @@ export interface AllowedComponentProps { // Note: can't mark this whole interface internal because some public interfaces // extend it. export interface ComponentInternalOptions { - /** - * @internal - */ - __props?: NormalizedPropsOptions - /** - * @internal - */ - __emits?: ObjectEmitsOptions | null /** * @internal */ diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index 44f9765d..b7fbec48 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -172,8 +172,10 @@ export function normalizeEmitsOptions( appContext: AppContext, asMixin = false ): ObjectEmitsOptions | null { - if (!appContext.deopt && comp.__emits !== undefined) { - return comp.__emits + const cache = appContext.emitsCache + const cached = cache.get(comp) + if (cached !== undefined) { + return cached } const raw = comp.emits @@ -201,7 +203,8 @@ export function normalizeEmitsOptions( } if (!raw && !hasExtends) { - return (comp.__emits = null) + cache.set(comp, null) + return null } if (isArray(raw)) { @@ -209,7 +212,9 @@ export function normalizeEmitsOptions( } else { extend(normalized, raw) } - return (comp.__emits = normalized) + + cache.set(comp, normalized) + return normalized } // Check if an incoming prop key is a declared emit event listener. diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 3983e8d9..11c42fcd 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -894,7 +894,7 @@ export function resolveMergedOptions( const { mixins, extends: extendsOptions } = base const { mixins: globalMixins, - cache, + optionsCache: cache, config: { optionMergeStrategies } } = instance.appContext const cached = cache.get(base) diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 3c9afc7c..b83f0abb 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -436,8 +436,10 @@ export function normalizePropsOptions( appContext: AppContext, asMixin = false ): NormalizedPropsOptions { - if (!appContext.deopt && comp.__props) { - return comp.__props + const cache = appContext.propsCache + const cached = cache.get(comp) + if (cached) { + return cached } const raw = comp.props @@ -468,7 +470,8 @@ export function normalizePropsOptions( } if (!raw && !hasExtends) { - return (comp.__props = EMPTY_ARR as any) + cache.set(comp, EMPTY_ARR as any) + return EMPTY_ARR as any } if (isArray(raw)) { @@ -506,7 +509,9 @@ export function normalizePropsOptions( } } - return (comp.__props = [normalized, needCastKeys]) + const res: NormalizedPropsOptions = [normalized, needCastKeys] + cache.set(comp, res) + return res } function validatePropName(key: string) {