perf: avoid deopt for props/emits normalization when global mixins are used
This commit is contained in:
parent
e2ca67b59a
commit
51d2be2038
@ -20,6 +20,8 @@ import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
|
|||||||
import { isFunction, NO, isObject } from '@vue/shared'
|
import { isFunction, NO, isObject } from '@vue/shared'
|
||||||
import { version } from '.'
|
import { version } from '.'
|
||||||
import { installAppCompatProperties } from './compat/global'
|
import { installAppCompatProperties } from './compat/global'
|
||||||
|
import { NormalizedPropsOptions } from './componentProps'
|
||||||
|
import { ObjectEmitsOptions } from './componentEmits'
|
||||||
|
|
||||||
export interface App<HostElement = any> {
|
export interface App<HostElement = any> {
|
||||||
version: string
|
version: string
|
||||||
@ -101,13 +103,19 @@ export interface AppContext {
|
|||||||
* Cache for merged/normalized component options
|
* Cache for merged/normalized component options
|
||||||
* Each app instance has its own cache because app-level global mixins and
|
* Each app instance has its own cache because app-level global mixins and
|
||||||
* optionMergeStrategies can affect merge behavior.
|
* optionMergeStrategies can affect merge behavior.
|
||||||
*/
|
|
||||||
cache: WeakMap<ComponentOptions, MergedComponentOptions>
|
|
||||||
/**
|
|
||||||
* Flag for de-optimizing props normalization
|
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
deopt?: boolean
|
optionsCache: WeakMap<ComponentOptions, MergedComponentOptions>
|
||||||
|
/**
|
||||||
|
* Cache for normalized props options
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
propsCache: WeakMap<ConcreteComponent, NormalizedPropsOptions>
|
||||||
|
/**
|
||||||
|
* Cache for normalized emits options
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
emitsCache: WeakMap<ConcreteComponent, ObjectEmitsOptions | null>
|
||||||
/**
|
/**
|
||||||
* HMR only
|
* HMR only
|
||||||
* @internal
|
* @internal
|
||||||
@ -144,7 +152,9 @@ export function createAppContext(): AppContext {
|
|||||||
components: {},
|
components: {},
|
||||||
directives: {},
|
directives: {},
|
||||||
provides: Object.create(null),
|
provides: Object.create(null),
|
||||||
cache: new WeakMap()
|
optionsCache: new WeakMap(),
|
||||||
|
propsCache: new WeakMap(),
|
||||||
|
emitsCache: new WeakMap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,11 +223,6 @@ export function createAppAPI<HostElement>(
|
|||||||
if (__FEATURE_OPTIONS_API__) {
|
if (__FEATURE_OPTIONS_API__) {
|
||||||
if (!context.mixins.includes(mixin)) {
|
if (!context.mixins.includes(mixin)) {
|
||||||
context.mixins.push(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__) {
|
} else if (__DEV__) {
|
||||||
warn(
|
warn(
|
||||||
'Mixin has already been applied to target app' +
|
'Mixin has already been applied to target app' +
|
||||||
|
@ -76,14 +76,6 @@ export interface AllowedComponentProps {
|
|||||||
// Note: can't mark this whole interface internal because some public interfaces
|
// Note: can't mark this whole interface internal because some public interfaces
|
||||||
// extend it.
|
// extend it.
|
||||||
export interface ComponentInternalOptions {
|
export interface ComponentInternalOptions {
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
__props?: NormalizedPropsOptions
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
__emits?: ObjectEmitsOptions | null
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -172,8 +172,10 @@ export function normalizeEmitsOptions(
|
|||||||
appContext: AppContext,
|
appContext: AppContext,
|
||||||
asMixin = false
|
asMixin = false
|
||||||
): ObjectEmitsOptions | null {
|
): ObjectEmitsOptions | null {
|
||||||
if (!appContext.deopt && comp.__emits !== undefined) {
|
const cache = appContext.emitsCache
|
||||||
return comp.__emits
|
const cached = cache.get(comp)
|
||||||
|
if (cached !== undefined) {
|
||||||
|
return cached
|
||||||
}
|
}
|
||||||
|
|
||||||
const raw = comp.emits
|
const raw = comp.emits
|
||||||
@ -201,7 +203,8 @@ export function normalizeEmitsOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!raw && !hasExtends) {
|
if (!raw && !hasExtends) {
|
||||||
return (comp.__emits = null)
|
cache.set(comp, null)
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArray(raw)) {
|
if (isArray(raw)) {
|
||||||
@ -209,7 +212,9 @@ export function normalizeEmitsOptions(
|
|||||||
} else {
|
} else {
|
||||||
extend(normalized, raw)
|
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.
|
// Check if an incoming prop key is a declared emit event listener.
|
||||||
|
@ -894,7 +894,7 @@ export function resolveMergedOptions(
|
|||||||
const { mixins, extends: extendsOptions } = base
|
const { mixins, extends: extendsOptions } = base
|
||||||
const {
|
const {
|
||||||
mixins: globalMixins,
|
mixins: globalMixins,
|
||||||
cache,
|
optionsCache: cache,
|
||||||
config: { optionMergeStrategies }
|
config: { optionMergeStrategies }
|
||||||
} = instance.appContext
|
} = instance.appContext
|
||||||
const cached = cache.get(base)
|
const cached = cache.get(base)
|
||||||
|
@ -436,8 +436,10 @@ export function normalizePropsOptions(
|
|||||||
appContext: AppContext,
|
appContext: AppContext,
|
||||||
asMixin = false
|
asMixin = false
|
||||||
): NormalizedPropsOptions {
|
): NormalizedPropsOptions {
|
||||||
if (!appContext.deopt && comp.__props) {
|
const cache = appContext.propsCache
|
||||||
return comp.__props
|
const cached = cache.get(comp)
|
||||||
|
if (cached) {
|
||||||
|
return cached
|
||||||
}
|
}
|
||||||
|
|
||||||
const raw = comp.props
|
const raw = comp.props
|
||||||
@ -468,7 +470,8 @@ export function normalizePropsOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!raw && !hasExtends) {
|
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)) {
|
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) {
|
function validatePropName(key: string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user