fix(compiler): cache handlers should be per-instance, fix hoist w/ cached handlers

This commit is contained in:
Evan You
2019-10-20 17:00:11 -04:00
parent 39157f7671
commit 869ae19c41
9 changed files with 63 additions and 59 deletions

View File

@@ -83,7 +83,11 @@ export interface ComponentInternalInstance {
render: RenderFunction | null
effects: ReactiveEffect[] | null
provides: Data
accessCache: Data
// cache for renderProxy access type to avoid hasOwnProperty calls
accessCache: Data | null
// cache for render function values that rely on _ctx but won't need updates
// after initialized (e.g. inline handlers)
renderCache: any[] | null
components: Record<string, Component>
directives: Record<string, Directive>
@@ -149,6 +153,7 @@ export function createComponentInstance(
effects: null,
provides: parent ? parent.provides : Object.create(appContext.provides),
accessCache: null!,
renderCache: null,
// setup context properties
renderContext: EMPTY_OBJ,

View File

@@ -62,7 +62,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
// 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]
const n = accessCache![key]
if (n !== undefined) {
switch (n) {
case AccessTypes.DATA:
@@ -73,18 +73,20 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
return propsProxy![key]
}
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
accessCache[key] = AccessTypes.DATA
accessCache![key] = AccessTypes.DATA
return data[key]
} else if (hasOwn(renderContext, key)) {
accessCache[key] = AccessTypes.CONTEXT
accessCache![key] = AccessTypes.CONTEXT
return renderContext[key]
} else if (hasOwn(props, key)) {
// only cache props access if component has declared (thus stable) props
if (type.props != null) {
accessCache[key] = AccessTypes.PROPS
accessCache![key] = AccessTypes.PROPS
}
// return the value from propsProxy for ref unwrapping and readonly
return propsProxy![key]
} else if (key === '$cache') {
return target.renderCache || (target.renderCache = [])
} else if (key === '$el') {
return target.vnode.el
} else if (hasOwn(publicPropertiesMap, key)) {