wip: separate setupState
This commit is contained in:
parent
0709380c5f
commit
b2662a62c5
@ -35,7 +35,7 @@ describe('component: proxy', () => {
|
||||
expect(instance!.data.foo).toBe(2)
|
||||
})
|
||||
|
||||
test('renderContext', () => {
|
||||
test('setupState', () => {
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@ -55,7 +55,7 @@ describe('component: proxy', () => {
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
expect(instanceProxy.foo).toBe(1)
|
||||
instanceProxy.foo = 2
|
||||
expect(instance!.renderContext.foo).toBe(2)
|
||||
expect(instance!.setupState.foo).toBe(2)
|
||||
})
|
||||
|
||||
test('should not expose non-declared props', () => {
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
RuntimeCompiledPublicInstanceProxyHandlers,
|
||||
createDevProxyTarget,
|
||||
exposePropsOnDevProxyTarget,
|
||||
exposeRenderContextOnDevProxyTarget
|
||||
exposeSetupStateOnDevProxyTarget
|
||||
} from './componentProxy'
|
||||
import { ComponentPropsOptions, initProps } from './componentProps'
|
||||
import { Slots, initSlots, InternalSlots } from './componentSlots'
|
||||
@ -143,6 +143,13 @@ export interface ComponentInternalInstance {
|
||||
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
|
||||
@ -152,9 +159,6 @@ export interface ComponentInternalInstance {
|
||||
// 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
|
||||
@ -209,19 +213,20 @@ export function createComponentInstance(
|
||||
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),
|
||||
@ -392,9 +397,9 @@ export function handleSetupResult(
|
||||
}
|
||||
// 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(
|
||||
|
@ -76,9 +76,10 @@ const publicPropertiesMap: Record<
|
||||
}
|
||||
|
||||
const enum AccessTypes {
|
||||
SETUP,
|
||||
DATA,
|
||||
CONTEXT,
|
||||
PROPS,
|
||||
CONTEXT,
|
||||
OTHER
|
||||
}
|
||||
|
||||
@ -91,6 +92,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
get({ _: instance }: ComponentPublicProxyTarget, key: string) {
|
||||
const {
|
||||
renderContext,
|
||||
setupState,
|
||||
data,
|
||||
props,
|
||||
accessCache,
|
||||
@ -109,6 +111,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
const n = accessCache![key]
|
||||
if (n !== undefined) {
|
||||
switch (n) {
|
||||
case AccessTypes.SETUP:
|
||||
return setupState[key]
|
||||
case AccessTypes.DATA:
|
||||
return data[key]
|
||||
case AccessTypes.CONTEXT:
|
||||
@ -117,22 +121,25 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,9 +177,18 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
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 (key in instance.props) {
|
||||
__DEV__ &&
|
||||
warn(
|
||||
`Attempting to mutate prop "${key}". Props are readonly.`,
|
||||
instance
|
||||
)
|
||||
return false
|
||||
} else if (hasOwn(renderContext, key)) {
|
||||
renderContext[key] = value
|
||||
} else if (key[0] === '$' && key.slice(1) in instance) {
|
||||
@ -183,13 +199,6 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
instance
|
||||
)
|
||||
return false
|
||||
} else if (key in instance.props) {
|
||||
__DEV__ &&
|
||||
warn(
|
||||
`Attempting to mutate prop "${key}". Props are readonly.`,
|
||||
instance
|
||||
)
|
||||
return false
|
||||
} else {
|
||||
if (__DEV__ && key in instance.appContext.config.globalProperties) {
|
||||
Object.defineProperty(instance.proxyTarget, key, {
|
||||
@ -206,15 +215,24 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||
|
||||
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)
|
||||
@ -306,15 +324,15 @@ export function exposePropsOnDevProxyTarget(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
})
|
||||
|
@ -1899,14 +1899,14 @@ function baseCreateRenderer(
|
||||
}
|
||||
const oldRef = oldRawRef && oldRawRef[1]
|
||||
const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs
|
||||
const renderContext = owner.renderContext
|
||||
const setupState = owner.setupState
|
||||
|
||||
// unset old ref
|
||||
if (oldRef != null && oldRef !== ref) {
|
||||
if (isString(oldRef)) {
|
||||
refs[oldRef] = null
|
||||
if (hasOwn(renderContext, oldRef)) {
|
||||
renderContext[oldRef] = null
|
||||
if (hasOwn(setupState, oldRef)) {
|
||||
setupState[oldRef] = null
|
||||
}
|
||||
} else if (isRef(oldRef)) {
|
||||
oldRef.value = null
|
||||
@ -1915,8 +1915,8 @@ function baseCreateRenderer(
|
||||
|
||||
if (isString(ref)) {
|
||||
refs[ref] = value
|
||||
if (hasOwn(renderContext, ref)) {
|
||||
renderContext[ref] = value
|
||||
if (hasOwn(setupState, ref)) {
|
||||
setupState[ref] = value
|
||||
}
|
||||
} else if (isRef(ref)) {
|
||||
ref.value = value
|
||||
|
Loading…
Reference in New Issue
Block a user