refactor(runtime-core): refactor instance public proxy context object
This commit is contained in:
@@ -83,25 +83,24 @@ const enum AccessTypes {
|
||||
OTHER
|
||||
}
|
||||
|
||||
export interface ComponentPublicProxyTarget {
|
||||
export interface ComponentRenderContext {
|
||||
[key: string]: any
|
||||
_: ComponentInternalInstance
|
||||
}
|
||||
|
||||
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
get({ _: instance }: ComponentPublicProxyTarget, key: string) {
|
||||
get({ _: instance }: ComponentRenderContext, key: string) {
|
||||
const {
|
||||
renderContext,
|
||||
ctx,
|
||||
setupState,
|
||||
data,
|
||||
props,
|
||||
accessCache,
|
||||
type,
|
||||
proxyTarget,
|
||||
appContext
|
||||
} = instance
|
||||
|
||||
// data / props / renderContext
|
||||
// data / props / ctx
|
||||
// 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
|
||||
@@ -116,7 +115,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
case AccessTypes.DATA:
|
||||
return data[key]
|
||||
case AccessTypes.CONTEXT:
|
||||
return renderContext[key]
|
||||
return ctx[key]
|
||||
case AccessTypes.PROPS:
|
||||
return props![key]
|
||||
// default: just fallthrough
|
||||
@@ -135,31 +134,30 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
) {
|
||||
accessCache![key] = AccessTypes.PROPS
|
||||
return props![key]
|
||||
} else if (renderContext !== EMPTY_OBJ && hasOwn(renderContext, key)) {
|
||||
} else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {
|
||||
accessCache![key] = AccessTypes.CONTEXT
|
||||
return renderContext[key]
|
||||
return ctx[key]
|
||||
} else {
|
||||
accessCache![key] = AccessTypes.OTHER
|
||||
}
|
||||
}
|
||||
|
||||
// public $xxx properties &
|
||||
// user-attached properties (falls through to proxyTarget)
|
||||
const publicGetter = publicPropertiesMap[key]
|
||||
let cssModule, globalProperties
|
||||
// public $xxx properties
|
||||
if (publicGetter) {
|
||||
if (__DEV__ && key === '$attrs') {
|
||||
markAttrsAccessed()
|
||||
}
|
||||
return publicGetter(instance)
|
||||
} else if (hasOwn(proxyTarget, key)) {
|
||||
return proxyTarget[key]
|
||||
} else if (
|
||||
// css module (injected by vue-loader)
|
||||
(cssModule = type.__cssModules) &&
|
||||
(cssModule = cssModule[key])
|
||||
) {
|
||||
return cssModule
|
||||
} else if (
|
||||
// global properties
|
||||
((globalProperties = appContext.config.globalProperties),
|
||||
hasOwn(globalProperties, key))
|
||||
) {
|
||||
@@ -173,11 +171,11 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
},
|
||||
|
||||
set(
|
||||
{ _: instance }: ComponentPublicProxyTarget,
|
||||
{ _: instance }: ComponentRenderContext,
|
||||
key: string,
|
||||
value: any
|
||||
): boolean {
|
||||
const { data, setupState, renderContext } = instance
|
||||
const { data, setupState, ctx } = instance
|
||||
if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
|
||||
setupState[key] = value
|
||||
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
|
||||
@@ -189,9 +187,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
instance
|
||||
)
|
||||
return false
|
||||
} else if (hasOwn(renderContext, key)) {
|
||||
renderContext[key] = value
|
||||
} else if (key[0] === '$' && key.slice(1) in instance) {
|
||||
}
|
||||
if (key[0] === '$' && key.slice(1) in instance) {
|
||||
__DEV__ &&
|
||||
warn(
|
||||
`Attempting to mutate public property "${key}". ` +
|
||||
@@ -201,13 +198,13 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
return false
|
||||
} else {
|
||||
if (__DEV__ && key in instance.appContext.config.globalProperties) {
|
||||
Object.defineProperty(instance.proxyTarget, key, {
|
||||
configurable: true,
|
||||
Object.defineProperty(ctx, key, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
value
|
||||
})
|
||||
} else {
|
||||
instance.proxyTarget[key] = value
|
||||
ctx[key] = value
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -215,16 +212,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
|
||||
has(
|
||||
{
|
||||
_: {
|
||||
data,
|
||||
setupState,
|
||||
accessCache,
|
||||
renderContext,
|
||||
type,
|
||||
proxyTarget,
|
||||
appContext
|
||||
}
|
||||
}: ComponentPublicProxyTarget,
|
||||
_: { data, setupState, accessCache, ctx, type, appContext }
|
||||
}: ComponentRenderContext,
|
||||
key: string
|
||||
) {
|
||||
return (
|
||||
@@ -232,18 +221,15 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
(data !== EMPTY_OBJ && hasOwn(data, key)) ||
|
||||
(setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||
|
||||
(type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
|
||||
hasOwn(renderContext, key) ||
|
||||
hasOwn(ctx, key) ||
|
||||
hasOwn(publicPropertiesMap, key) ||
|
||||
hasOwn(proxyTarget, key) ||
|
||||
hasOwn(appContext.config.globalProperties, key)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (__DEV__ && !__TEST__) {
|
||||
PublicInstanceProxyHandlers.ownKeys = (
|
||||
target: ComponentPublicProxyTarget
|
||||
) => {
|
||||
PublicInstanceProxyHandlers.ownKeys = (target: ComponentRenderContext) => {
|
||||
warn(
|
||||
`Avoid app logic that relies on enumerating keys on a component instance. ` +
|
||||
`The keys will be empty in production mode to avoid performance overhead.`
|
||||
@@ -254,14 +240,14 @@ if (__DEV__ && !__TEST__) {
|
||||
|
||||
export const RuntimeCompiledPublicInstanceProxyHandlers = {
|
||||
...PublicInstanceProxyHandlers,
|
||||
get(target: ComponentPublicProxyTarget, key: string) {
|
||||
get(target: ComponentRenderContext, key: string) {
|
||||
// fast path for unscopables when using `with` block
|
||||
if ((key as any) === Symbol.unscopables) {
|
||||
return
|
||||
}
|
||||
return PublicInstanceProxyHandlers.get!(target, key, target)
|
||||
},
|
||||
has(_: ComponentPublicProxyTarget, key: string) {
|
||||
has(_: ComponentRenderContext, key: string) {
|
||||
return key[0] !== '_' && !isGloballyWhitelisted(key)
|
||||
}
|
||||
}
|
||||
@@ -269,7 +255,7 @@ export const RuntimeCompiledPublicInstanceProxyHandlers = {
|
||||
// In dev mode, the proxy target exposes the same properties as seen on `this`
|
||||
// for easier console inspection. In prod mode it will be an empty object so
|
||||
// these properties definitions can be skipped.
|
||||
export function createDevProxyTarget(instance: ComponentInternalInstance) {
|
||||
export function createRenderContext(instance: ComponentInternalInstance) {
|
||||
const target: Record<string, any> = {}
|
||||
|
||||
// expose internal instance for proxy handlers
|
||||
@@ -302,19 +288,20 @@ export function createDevProxyTarget(instance: ComponentInternalInstance) {
|
||||
})
|
||||
})
|
||||
|
||||
return target as ComponentPublicProxyTarget
|
||||
return target as ComponentRenderContext
|
||||
}
|
||||
|
||||
export function exposePropsOnDevProxyTarget(
|
||||
// dev only
|
||||
export function exposePropsOnRenderContext(
|
||||
instance: ComponentInternalInstance
|
||||
) {
|
||||
const {
|
||||
proxyTarget,
|
||||
ctx,
|
||||
type: { props: propsOptions }
|
||||
} = instance
|
||||
if (propsOptions) {
|
||||
Object.keys(normalizePropsOptions(propsOptions)[0]!).forEach(key => {
|
||||
Object.defineProperty(proxyTarget, key, {
|
||||
Object.defineProperty(ctx, key, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: () => instance.props[key],
|
||||
@@ -324,12 +311,13 @@ export function exposePropsOnDevProxyTarget(
|
||||
}
|
||||
}
|
||||
|
||||
export function exposeSetupStateOnDevProxyTarget(
|
||||
// dev only
|
||||
export function exposeSetupStateOnRenderContext(
|
||||
instance: ComponentInternalInstance
|
||||
) {
|
||||
const { proxyTarget, setupState } = instance
|
||||
const { ctx, setupState } = instance
|
||||
Object.keys(toRaw(setupState)).forEach(key => {
|
||||
Object.defineProperty(proxyTarget, key, {
|
||||
Object.defineProperty(ctx, key, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: () => setupState[key],
|
||||
|
||||
Reference in New Issue
Block a user