expect(isReactive(observed.array[0])).toBe(true)
})
+ test('process subtypes of collections properly', () => {
+ class CustomMap extends Map {
+ count = 0
+
+ set(key: any, value: any): this {
+ super.set(key, value)
+ this.count++
+ return this
+ }
+ }
+
+ const testMap = new CustomMap()
+ const observed = reactive(testMap)
+ expect(observed.count).toBe(0)
+ observed.set('test', 'value')
+ expect(observed.count).toBe(1)
+ })
+
test('observed value should proxy mutations to original (Object)', () => {
const original: any = { foo: 1 }
const observed = reactive(original)
-import { isObject, toRawType, def, hasOwn, makeMap } from '@vue/shared'
+import { isObject, toRawType, def, hasOwn } from '@vue/shared'
import {
mutableHandlers,
readonlyHandlers,
[ReactiveFlags.READONLY]?: any
}
-const collectionTypes = new Set<Function>([Set, Map, WeakMap, WeakSet])
-const isObservableType = /*#__PURE__*/ makeMap(
- 'Object,Array,Map,Set,WeakMap,WeakSet'
-)
+const enum TargetType {
+ INVALID = 0,
+ COMMON = 1,
+ COLLECTION = 2
+}
-const canObserve = (value: Target): boolean => {
- return (
- !value[ReactiveFlags.SKIP] &&
- isObservableType(toRawType(value)) &&
- Object.isExtensible(value)
- )
+function targetTypeMap(rawType: string) {
+ switch (rawType) {
+ case 'Object':
+ case 'Array':
+ return TargetType.COMMON
+ case 'Map':
+ case 'Set':
+ case 'WeakMap':
+ case 'WeakSet':
+ return TargetType.COLLECTION
+ default:
+ return TargetType.INVALID
+ }
+}
+
+function getTargetType(value: Target) {
+ return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
+ ? TargetType.INVALID
+ : targetTypeMap(toRawType(value))
}
// only unwrap nested ref
return target[reactiveFlag]
}
// only a whitelist of value types can be observed.
- if (!canObserve(target)) {
+ const targetType = getTargetType(target)
+ if (targetType === TargetType.INVALID) {
return target
}
const observed = new Proxy(
target,
- collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers
+ targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
)
def(target, reactiveFlag, observed)
return observed