Skip to content

Commit 51d2be2

Browse files
committed
perf: avoid deopt for props/emits normalization when global mixins are used
1 parent e2ca67b commit 51d2be2

File tree

5 files changed

+33
-26
lines changed

5 files changed

+33
-26
lines changed

packages/runtime-core/src/apiCreateApp.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
2020
import { isFunction, NO, isObject } from '@vue/shared'
2121
import { version } from '.'
2222
import { installAppCompatProperties } from './compat/global'
23+
import { NormalizedPropsOptions } from './componentProps'
24+
import { ObjectEmitsOptions } from './componentEmits'
2325

2426
export interface App<HostElement = any> {
2527
version: string
@@ -101,13 +103,19 @@ export interface AppContext {
101103
* Cache for merged/normalized component options
102104
* Each app instance has its own cache because app-level global mixins and
103105
* optionMergeStrategies can affect merge behavior.
106+
* @internal
104107
*/
105-
cache: WeakMap<ComponentOptions, MergedComponentOptions>
108+
optionsCache: WeakMap<ComponentOptions, MergedComponentOptions>
106109
/**
107-
* Flag for de-optimizing props normalization
110+
* Cache for normalized props options
108111
* @internal
109112
*/
110-
deopt?: boolean
113+
propsCache: WeakMap<ConcreteComponent, NormalizedPropsOptions>
114+
/**
115+
* Cache for normalized emits options
116+
* @internal
117+
*/
118+
emitsCache: WeakMap<ConcreteComponent, ObjectEmitsOptions | null>
111119
/**
112120
* HMR only
113121
* @internal
@@ -144,7 +152,9 @@ export function createAppContext(): AppContext {
144152
components: {},
145153
directives: {},
146154
provides: Object.create(null),
147-
cache: new WeakMap()
155+
optionsCache: new WeakMap(),
156+
propsCache: new WeakMap(),
157+
emitsCache: new WeakMap()
148158
}
149159
}
150160

@@ -213,11 +223,6 @@ export function createAppAPI<HostElement>(
213223
if (__FEATURE_OPTIONS_API__) {
214224
if (!context.mixins.includes(mixin)) {
215225
context.mixins.push(mixin)
216-
// global mixin with props/emits de-optimizes props/emits
217-
// normalization caching.
218-
if (mixin.props || mixin.emits) {
219-
context.deopt = true
220-
}
221226
} else if (__DEV__) {
222227
warn(
223228
'Mixin has already been applied to target app' +

packages/runtime-core/src/component.ts

-8
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ export interface AllowedComponentProps {
7676
// Note: can't mark this whole interface internal because some public interfaces
7777
// extend it.
7878
export interface ComponentInternalOptions {
79-
/**
80-
* @internal
81-
*/
82-
__props?: NormalizedPropsOptions
83-
/**
84-
* @internal
85-
*/
86-
__emits?: ObjectEmitsOptions | null
8779
/**
8880
* @internal
8981
*/

packages/runtime-core/src/componentEmits.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,10 @@ export function normalizeEmitsOptions(
172172
appContext: AppContext,
173173
asMixin = false
174174
): ObjectEmitsOptions | null {
175-
if (!appContext.deopt && comp.__emits !== undefined) {
176-
return comp.__emits
175+
const cache = appContext.emitsCache
176+
const cached = cache.get(comp)
177+
if (cached !== undefined) {
178+
return cached
177179
}
178180

179181
const raw = comp.emits
@@ -201,15 +203,18 @@ export function normalizeEmitsOptions(
201203
}
202204

203205
if (!raw && !hasExtends) {
204-
return (comp.__emits = null)
206+
cache.set(comp, null)
207+
return null
205208
}
206209

207210
if (isArray(raw)) {
208211
raw.forEach(key => (normalized[key] = null))
209212
} else {
210213
extend(normalized, raw)
211214
}
212-
return (comp.__emits = normalized)
215+
216+
cache.set(comp, normalized)
217+
return normalized
213218
}
214219

215220
// Check if an incoming prop key is a declared emit event listener.

packages/runtime-core/src/componentOptions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ export function resolveMergedOptions(
894894
const { mixins, extends: extendsOptions } = base
895895
const {
896896
mixins: globalMixins,
897-
cache,
897+
optionsCache: cache,
898898
config: { optionMergeStrategies }
899899
} = instance.appContext
900900
const cached = cache.get(base)

packages/runtime-core/src/componentProps.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,10 @@ export function normalizePropsOptions(
436436
appContext: AppContext,
437437
asMixin = false
438438
): NormalizedPropsOptions {
439-
if (!appContext.deopt && comp.__props) {
440-
return comp.__props
439+
const cache = appContext.propsCache
440+
const cached = cache.get(comp)
441+
if (cached) {
442+
return cached
441443
}
442444

443445
const raw = comp.props
@@ -468,7 +470,8 @@ export function normalizePropsOptions(
468470
}
469471

470472
if (!raw && !hasExtends) {
471-
return (comp.__props = EMPTY_ARR as any)
473+
cache.set(comp, EMPTY_ARR as any)
474+
return EMPTY_ARR as any
472475
}
473476

474477
if (isArray(raw)) {
@@ -506,7 +509,9 @@ export function normalizePropsOptions(
506509
}
507510
}
508511

509-
return (comp.__props = [normalized, needCastKeys])
512+
const res: NormalizedPropsOptions = [normalized, needCastKeys]
513+
cache.set(comp, res)
514+
return res
510515
}
511516

512517
function validatePropName(key: string) {

0 commit comments

Comments
 (0)