fix(reactivity): Map/Set identity methods should work even if raw value contains reactive entries

fix #799
This commit is contained in:
Evan You
2020-03-06 11:10:02 -05:00
parent 16f9e63951
commit cc69fd72e3
5 changed files with 63 additions and 13 deletions

View File

@@ -26,16 +26,22 @@ function get(
wrap: typeof toReactive | typeof toReadonly
) {
target = toRaw(target)
key = toRaw(key)
track(target, TrackOpTypes.GET, key)
return wrap(getProto(target).get.call(target, key))
const rawKey = toRaw(key)
track(target, TrackOpTypes.GET, rawKey)
const { has, get } = getProto(target)
if (has.call(target, key)) {
return wrap(get.call(target, key))
} else if (has.call(target, rawKey)) {
return wrap(get.call(target, rawKey))
}
}
function has(this: CollectionTypes, key: unknown): boolean {
const target = toRaw(this)
key = toRaw(key)
track(target, TrackOpTypes.HAS, key)
return getProto(target).has.call(target, key)
const rawKey = toRaw(key)
track(target, TrackOpTypes.HAS, rawKey)
const has = getProto(target).has
return has.call(target, key) || has.call(target, rawKey)
}
function size(target: IterableCollections) {
@@ -73,13 +79,16 @@ function set(this: MapTypes, key: unknown, value: unknown) {
}
function deleteEntry(this: CollectionTypes, key: unknown) {
key = toRaw(key)
const target = toRaw(this)
const proto = getProto(target)
const hadKey = proto.has.call(target, key)
const oldValue = proto.get ? proto.get.call(target, key) : undefined
const { has, get, delete: del } = getProto(target)
let hadKey = has.call(target, key)
if (!hadKey) {
key = toRaw(key)
hadKey = has.call(target, key)
}
const oldValue = get ? get.call(target, key) : undefined
// forward the operation before queueing reactions
const result = proto.delete.call(target, key)
const result = del.call(target, key)
if (hadKey) {
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
}
@@ -177,7 +186,7 @@ const mutableInstrumentations: Record<string, Function> = {
return get(this, key, toReactive)
},
get size() {
return size(this as unknown as IterableCollections)
return size((this as unknown) as IterableCollections)
},
has,
add,