fix(reactivity): accept subtypes of collections (#1864)

This commit is contained in:
ᴜɴвʏтᴇ
2020-08-18 00:17:46 +08:00
committed by GitHub
parent 6ccd9ac2bc
commit d005b578b1
2 changed files with 46 additions and 13 deletions

View File

@@ -1,4 +1,4 @@
import { isObject, toRawType, def, hasOwn, makeMap } from '@vue/shared'
import { isObject, toRawType, def, hasOwn } from '@vue/shared'
import {
mutableHandlers,
readonlyHandlers,
@@ -30,17 +30,31 @@ export interface Target {
[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
@@ -148,12 +162,13 @@ function createReactiveObject(
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