|
|
@@ -26,7 +26,6 @@ import {
|
|
|
hasChanged,
|
|
|
isArray,
|
|
|
isIntegerKey,
|
|
|
- extend,
|
|
|
makeMap
|
|
|
} from '@vue/shared'
|
|
|
import { isRef } from './ref'
|
|
|
@@ -45,11 +44,6 @@ const builtInSymbols = new Set(
|
|
|
.filter(isSymbol)
|
|
|
)
|
|
|
|
|
|
-const get = /*#__PURE__*/ createGetter()
|
|
|
-const shallowGet = /*#__PURE__*/ createGetter(false, true)
|
|
|
-const readonlyGet = /*#__PURE__*/ createGetter(true)
|
|
|
-const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)
|
|
|
-
|
|
|
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations()
|
|
|
|
|
|
function createArrayInstrumentations() {
|
|
|
@@ -91,8 +85,15 @@ function hasOwnProperty(this: object, key: string) {
|
|
|
return obj.hasOwnProperty(key)
|
|
|
}
|
|
|
|
|
|
-function createGetter(isReadonly = false, shallow = false) {
|
|
|
- return function get(target: Target, key: string | symbol, receiver: object) {
|
|
|
+class BaseReactiveHandler implements ProxyHandler<Target> {
|
|
|
+ constructor(
|
|
|
+ protected readonly _isReadonly = false,
|
|
|
+ protected readonly _shallow = false
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ get(target: Target, key: string | symbol, receiver: object) {
|
|
|
+ const isReadonly = this._isReadonly,
|
|
|
+ shallow = this._shallow
|
|
|
if (key === ReactiveFlags.IS_REACTIVE) {
|
|
|
return !isReadonly
|
|
|
} else if (key === ReactiveFlags.IS_READONLY) {
|
|
|
@@ -155,11 +156,12 @@ function createGetter(isReadonly = false, shallow = false) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const set = /*#__PURE__*/ createSetter()
|
|
|
-const shallowSet = /*#__PURE__*/ createSetter(true)
|
|
|
+class MutableReactiveHandler extends BaseReactiveHandler {
|
|
|
+ constructor(shallow = false) {
|
|
|
+ super(false, shallow)
|
|
|
+ }
|
|
|
|
|
|
-function createSetter(shallow = false) {
|
|
|
- return function set(
|
|
|
+ set(
|
|
|
target: object,
|
|
|
key: string | symbol,
|
|
|
value: unknown,
|
|
|
@@ -169,7 +171,7 @@ function createSetter(shallow = false) {
|
|
|
if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
|
|
|
return false
|
|
|
}
|
|
|
- if (!shallow) {
|
|
|
+ if (!this._shallow) {
|
|
|
if (!isShallow(value) && !isReadonly(value)) {
|
|
|
oldValue = toRaw(oldValue)
|
|
|
value = toRaw(value)
|
|
|
@@ -197,42 +199,40 @@ function createSetter(shallow = false) {
|
|
|
}
|
|
|
return result
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-function deleteProperty(target: object, key: string | symbol): boolean {
|
|
|
- const hadKey = hasOwn(target, key)
|
|
|
- const oldValue = (target as any)[key]
|
|
|
- const result = Reflect.deleteProperty(target, key)
|
|
|
- if (result && hadKey) {
|
|
|
- trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
|
|
|
+ deleteProperty(target: object, key: string | symbol): boolean {
|
|
|
+ const hadKey = hasOwn(target, key)
|
|
|
+ const oldValue = (target as any)[key]
|
|
|
+ const result = Reflect.deleteProperty(target, key)
|
|
|
+ if (result && hadKey) {
|
|
|
+ trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
|
|
|
+ }
|
|
|
+ return result
|
|
|
}
|
|
|
- return result
|
|
|
-}
|
|
|
|
|
|
-function has(target: object, key: string | symbol): boolean {
|
|
|
- const result = Reflect.has(target, key)
|
|
|
- if (!isSymbol(key) || !builtInSymbols.has(key)) {
|
|
|
- track(target, TrackOpTypes.HAS, key)
|
|
|
+ has(target: object, key: string | symbol): boolean {
|
|
|
+ const result = Reflect.has(target, key)
|
|
|
+ if (!isSymbol(key) || !builtInSymbols.has(key)) {
|
|
|
+ track(target, TrackOpTypes.HAS, key)
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ }
|
|
|
+ ownKeys(target: object): (string | symbol)[] {
|
|
|
+ track(
|
|
|
+ target,
|
|
|
+ TrackOpTypes.ITERATE,
|
|
|
+ isArray(target) ? 'length' : ITERATE_KEY
|
|
|
+ )
|
|
|
+ return Reflect.ownKeys(target)
|
|
|
}
|
|
|
- return result
|
|
|
-}
|
|
|
-
|
|
|
-function ownKeys(target: object): (string | symbol)[] {
|
|
|
- track(target, TrackOpTypes.ITERATE, isArray(target) ? 'length' : ITERATE_KEY)
|
|
|
- return Reflect.ownKeys(target)
|
|
|
}
|
|
|
|
|
|
-export const mutableHandlers: ProxyHandler<object> = {
|
|
|
- get,
|
|
|
- set,
|
|
|
- deleteProperty,
|
|
|
- has,
|
|
|
- ownKeys
|
|
|
-}
|
|
|
+class ReadonlyReactiveHandler extends BaseReactiveHandler {
|
|
|
+ constructor(shallow = false) {
|
|
|
+ super(true, shallow)
|
|
|
+ }
|
|
|
|
|
|
-export const readonlyHandlers: ProxyHandler<object> = {
|
|
|
- get: readonlyGet,
|
|
|
- set(target, key) {
|
|
|
+ set(target: object, key: string | symbol) {
|
|
|
if (__DEV__) {
|
|
|
warn(
|
|
|
`Set operation on key "${String(key)}" failed: target is readonly.`,
|
|
|
@@ -240,8 +240,9 @@ export const readonlyHandlers: ProxyHandler<object> = {
|
|
|
)
|
|
|
}
|
|
|
return true
|
|
|
- },
|
|
|
- deleteProperty(target, key) {
|
|
|
+ }
|
|
|
+
|
|
|
+ deleteProperty(target: object, key: string | symbol) {
|
|
|
if (__DEV__) {
|
|
|
warn(
|
|
|
`Delete operation on key "${String(key)}" failed: target is readonly.`,
|
|
|
@@ -252,22 +253,18 @@ export const readonlyHandlers: ProxyHandler<object> = {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export const shallowReactiveHandlers = /*#__PURE__*/ extend(
|
|
|
- {},
|
|
|
- mutableHandlers,
|
|
|
- {
|
|
|
- get: shallowGet,
|
|
|
- set: shallowSet
|
|
|
- }
|
|
|
+export const mutableHandlers: ProxyHandler<object> =
|
|
|
+ /*#__PURE__*/ new MutableReactiveHandler()
|
|
|
+
|
|
|
+export const readonlyHandlers: ProxyHandler<object> =
|
|
|
+ /*#__PURE__*/ new ReadonlyReactiveHandler()
|
|
|
+
|
|
|
+export const shallowReactiveHandlers = /*#__PURE__*/ new MutableReactiveHandler(
|
|
|
+ true
|
|
|
)
|
|
|
|
|
|
// Props handlers are special in the sense that it should not unwrap top-level
|
|
|
// refs (in order to allow refs to be explicitly passed down), but should
|
|
|
// retain the reactivity of the normal readonly object.
|
|
|
-export const shallowReadonlyHandlers = /*#__PURE__*/ extend(
|
|
|
- {},
|
|
|
- readonlyHandlers,
|
|
|
- {
|
|
|
- get: shallowReadonlyGet
|
|
|
- }
|
|
|
-)
|
|
|
+export const shallowReadonlyHandlers =
|
|
|
+ /*#__PURE__*/ new ReadonlyReactiveHandler(true)
|