RuntimeCompiledPublicInstanceProxyHandlers,
createDevProxyTarget,
exposePropsOnDevProxyTarget,
- exposeRenderContextOnDevProxyTarget
+ exposeSetupStateOnDevProxyTarget
} from './componentProxy'
import { ComponentPropsOptions, initProps } from './componentProps'
import { Slots, initSlots, InternalSlots } from './componentSlots'
attrs: Data
slots: InternalSlots
proxy: ComponentPublicInstance | null
+ refs: Data
+ emit: EmitFn
+
+ // setup
+ setupState: Data
+ setupContext: SetupContext | null
+
// The target object for the public instance proxy. In dev mode, we also
// define getters for all known instance properties on it so it can be
// properly inspected in the console. These getters are skipped in prod mode
// alternative proxy used only for runtime-compiled render functions using
// `with` block
withProxy: ComponentPublicInstance | null
- setupContext: SetupContext | null
- refs: Data
- emit: EmitFn
// suspense related
suspense: SuspenseBoundary | null
proxy: null,
proxyTarget: null!, // to be immediately set
withProxy: null,
- setupContext: null,
effects: null,
provides: parent ? parent.provides : Object.create(appContext.provides),
accessCache: null!,
renderCache: [],
- // setup context properties
+ // state
renderContext: EMPTY_OBJ,
data: EMPTY_OBJ,
props: EMPTY_OBJ,
attrs: EMPTY_OBJ,
slots: EMPTY_OBJ,
refs: EMPTY_OBJ,
+ setupState: EMPTY_OBJ,
+ setupContext: null,
// per-instance asset storage (mutable during options resolution)
components: Object.create(appContext.components),
}
// setup returned bindings.
// assuming a render function compiled from template is present.
- instance.renderContext = reactive(setupResult)
+ instance.setupState = reactive(setupResult)
if (__DEV__) {
- exposeRenderContextOnDevProxyTarget(instance)
+ exposeSetupStateOnDevProxyTarget(instance)
}
} else if (__DEV__ && setupResult !== undefined) {
warn(
}
const enum AccessTypes {
+ SETUP,
DATA,
- CONTEXT,
PROPS,
+ CONTEXT,
OTHER
}
get({ _: instance }: ComponentPublicProxyTarget, key: string) {
const {
renderContext,
+ setupState,
data,
props,
accessCache,
const n = accessCache![key]
if (n !== undefined) {
switch (n) {
+ case AccessTypes.SETUP:
+ return setupState[key]
case AccessTypes.DATA:
return data[key]
case AccessTypes.CONTEXT:
return props![key]
// default: just fallthrough
}
+ } else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
+ accessCache![key] = AccessTypes.SETUP
+ return setupState[key]
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
accessCache![key] = AccessTypes.DATA
return data[key]
+ } else if (
+ // only cache other properties when instance has declared (thus stable)
+ // props
+ type.props &&
+ hasOwn(normalizePropsOptions(type.props)[0]!, key)
+ ) {
+ accessCache![key] = AccessTypes.PROPS
+ return props![key]
} else if (renderContext !== EMPTY_OBJ && hasOwn(renderContext, key)) {
accessCache![key] = AccessTypes.CONTEXT
return renderContext[key]
- } else if (type.props) {
- // only cache other properties when instance has declared (thus stable)
- // props
- if (hasOwn(normalizePropsOptions(type.props)[0]!, key)) {
- accessCache![key] = AccessTypes.PROPS
- // return the value from propsProxy for ref unwrapping and readonly
- return props![key]
- } else {
- accessCache![key] = AccessTypes.OTHER
- }
+ } else {
+ accessCache![key] = AccessTypes.OTHER
}
}
key: string,
value: any
): boolean {
- const { data, renderContext } = instance
- if (data !== EMPTY_OBJ && hasOwn(data, key)) {
+ const { data, setupState, renderContext } = instance
+ if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
+ setupState[key] = value
+ } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
data[key] = value
- } else if (hasOwn(renderContext, key)) {
- renderContext[key] = value
- } else if (key[0] === '$' && key.slice(1) in instance) {
+ } else if (key in instance.props) {
__DEV__ &&
warn(
- `Attempting to mutate public property "${key}". ` +
- `Properties starting with $ are reserved and readonly.`,
+ `Attempting to mutate prop "${key}". Props are readonly.`,
instance
)
return false
- } else if (key in instance.props) {
+ } else if (hasOwn(renderContext, key)) {
+ renderContext[key] = value
+ } else if (key[0] === '$' && key.slice(1) in instance) {
__DEV__ &&
warn(
- `Attempting to mutate prop "${key}". Props are readonly.`,
+ `Attempting to mutate public property "${key}". ` +
+ `Properties starting with $ are reserved and readonly.`,
instance
)
return false
has(
{
- _: { data, accessCache, renderContext, type, proxyTarget, appContext }
+ _: {
+ data,
+ setupState,
+ accessCache,
+ renderContext,
+ type,
+ proxyTarget,
+ appContext
+ }
}: ComponentPublicProxyTarget,
key: string
) {
return (
accessCache![key] !== undefined ||
(data !== EMPTY_OBJ && hasOwn(data, key)) ||
- hasOwn(renderContext, key) ||
+ (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||
(type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
+ hasOwn(renderContext, key) ||
hasOwn(publicPropertiesMap, key) ||
hasOwn(proxyTarget, key) ||
hasOwn(appContext.config.globalProperties, key)
}
}
-export function exposeRenderContextOnDevProxyTarget(
+export function exposeSetupStateOnDevProxyTarget(
instance: ComponentInternalInstance
) {
- const { proxyTarget, renderContext } = instance
- Object.keys(toRaw(renderContext)).forEach(key => {
+ const { proxyTarget, setupState } = instance
+ Object.keys(toRaw(setupState)).forEach(key => {
Object.defineProperty(proxyTarget, key, {
enumerable: true,
configurable: true,
- get: () => renderContext[key],
+ get: () => setupState[key],
set: NOOP
})
})