|
|
@@ -349,6 +349,10 @@ export interface ComponentInternalInstance {
|
|
|
slots: InternalSlots
|
|
|
refs: Data
|
|
|
emit: EmitFn
|
|
|
+
|
|
|
+ attrsProxy: Data | null
|
|
|
+ slotsProxy: Slots | null
|
|
|
+
|
|
|
/**
|
|
|
* used for keeping track of .once event handlers on components
|
|
|
* @internal
|
|
|
@@ -536,6 +540,9 @@ export function createComponentInstance(
|
|
|
setupState: EMPTY_OBJ,
|
|
|
setupContext: null,
|
|
|
|
|
|
+ attrsProxy: null,
|
|
|
+ slotsProxy: null,
|
|
|
+
|
|
|
// suspense related
|
|
|
suspense,
|
|
|
suspenseId: suspense ? suspense.pendingId : 0,
|
|
|
@@ -923,31 +930,57 @@ export function finishComponentSetup(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function createAttrsProxy(instance: ComponentInternalInstance): Data {
|
|
|
- return new Proxy(
|
|
|
- instance.attrs,
|
|
|
- __DEV__
|
|
|
- ? {
|
|
|
- get(target, key: string) {
|
|
|
- markAttrsAccessed()
|
|
|
- track(instance, TrackOpTypes.GET, '$attrs')
|
|
|
- return target[key]
|
|
|
- },
|
|
|
- set() {
|
|
|
- warn(`setupContext.attrs is readonly.`)
|
|
|
- return false
|
|
|
- },
|
|
|
- deleteProperty() {
|
|
|
- warn(`setupContext.attrs is readonly.`)
|
|
|
- return false
|
|
|
+function getAttrsProxy(instance: ComponentInternalInstance): Data {
|
|
|
+ return (
|
|
|
+ instance.attrsProxy ||
|
|
|
+ (instance.attrsProxy = new Proxy(
|
|
|
+ instance.attrs,
|
|
|
+ __DEV__
|
|
|
+ ? {
|
|
|
+ get(target, key: string) {
|
|
|
+ markAttrsAccessed()
|
|
|
+ track(instance, TrackOpTypes.GET, '$attrs')
|
|
|
+ return target[key]
|
|
|
+ },
|
|
|
+ set() {
|
|
|
+ warn(`setupContext.attrs is readonly.`)
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ deleteProperty() {
|
|
|
+ warn(`setupContext.attrs is readonly.`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- : {
|
|
|
- get(target, key: string) {
|
|
|
- track(instance, TrackOpTypes.GET, '$attrs')
|
|
|
- return target[key]
|
|
|
+ : {
|
|
|
+ get(target, key: string) {
|
|
|
+ track(instance, TrackOpTypes.GET, '$attrs')
|
|
|
+ return target[key]
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
+ ))
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Dev-only
|
|
|
+ */
|
|
|
+function getSlotsProxy(instance: ComponentInternalInstance): Slots {
|
|
|
+ return (
|
|
|
+ instance.slotsProxy ||
|
|
|
+ (instance.slotsProxy = new Proxy(instance.slots, {
|
|
|
+ get(target, key: string) {
|
|
|
+ track(instance, TrackOpTypes.GET, '$slots')
|
|
|
+ return target[key]
|
|
|
+ },
|
|
|
+ set() {
|
|
|
+ warn(`setupContext.slots is readonly.`)
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ deleteProperty() {
|
|
|
+ warn(`setupContext.slots is readonly.`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }))
|
|
|
)
|
|
|
}
|
|
|
|
|
|
@@ -978,16 +1011,15 @@ export function createSetupContext(
|
|
|
instance.exposed = exposed || {}
|
|
|
}
|
|
|
|
|
|
- let attrs: Data
|
|
|
if (__DEV__) {
|
|
|
// We use getters in dev in case libs like test-utils overwrite instance
|
|
|
// properties (overwrites should not be done in prod)
|
|
|
return Object.freeze({
|
|
|
get attrs() {
|
|
|
- return attrs || (attrs = createAttrsProxy(instance))
|
|
|
+ return getAttrsProxy(instance)
|
|
|
},
|
|
|
get slots() {
|
|
|
- return shallowReadonly(instance.slots)
|
|
|
+ return getSlotsProxy(instance)
|
|
|
},
|
|
|
get emit() {
|
|
|
return (event: string, ...args: any[]) => instance.emit(event, ...args)
|
|
|
@@ -997,7 +1029,7 @@ export function createSetupContext(
|
|
|
} else {
|
|
|
return {
|
|
|
get attrs() {
|
|
|
- return attrs || (attrs = createAttrsProxy(instance))
|
|
|
+ return getAttrsProxy(instance)
|
|
|
},
|
|
|
slots: instance.slots,
|
|
|
emit: instance.emit,
|