perf(core): cache property access types on renderProxy

This commit is contained in:
Evan You
2019-10-16 22:13:52 -04:00
parent cdee65aa1b
commit 4771319a15
2 changed files with 30 additions and 3 deletions

View File

@@ -48,14 +48,38 @@ const publicPropertiesMap = {
$options: 'type'
}
const enum AccessTypes {
DATA,
CONTEXT,
PROPS
}
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
get(target: ComponentInternalInstance, key: string) {
const { renderContext, data, props, propsProxy } = target
if (data !== EMPTY_OBJ && hasOwn(data, key)) {
const { renderContext, data, props, propsProxy, accessCache } = target
// This getter gets called for every property access on the render context
// during render and is a major hotspot. The most expensive part of this
// is the multiple hasOwn() calls. It's much faster to do a simple property
// access on a plain object, so we use an accessCache object (with null
// prototype) to memoize what access type a key corresponds to.
const n = accessCache[key]
if (n !== undefined) {
switch (n) {
case AccessTypes.DATA:
return data[key]
case AccessTypes.CONTEXT:
return renderContext[key]
case AccessTypes.PROPS:
return propsProxy![key]
}
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
accessCache[key] = AccessTypes.DATA
return data[key]
} else if (hasOwn(renderContext, key)) {
accessCache[key] = AccessTypes.CONTEXT
return renderContext[key]
} else if (hasOwn(props, key)) {
accessCache[key] = AccessTypes.PROPS
// return the value from propsProxy for ref unwrapping and readonly
return propsProxy![key]
} else if (key === '$el') {