From 63686133e35ff8dee7b8e8b22713b12755ddfdb0 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Thu, 9 Jan 2020 15:12:36 +0800 Subject: [PATCH 1/2] fix(reactivity): should delete observe value (#597) --- .../__tests__/collections/Map.spec.ts | 17 ++++++++++++++++- .../__tests__/collections/Set.spec.ts | 15 ++++++++++++++- .../__tests__/collections/WeakMap.spec.ts | 18 +++++++++++++++++- .../__tests__/collections/WeakSet.spec.ts | 15 ++++++++++++++- packages/reactivity/src/collectionHandlers.ts | 7 ++++--- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/packages/reactivity/__tests__/collections/Map.spec.ts b/packages/reactivity/__tests__/collections/Map.spec.ts index b190da32fce..cb8f0ebe34a 100644 --- a/packages/reactivity/__tests__/collections/Map.spec.ts +++ b/packages/reactivity/__tests__/collections/Map.spec.ts @@ -1,4 +1,4 @@ -import { reactive, effect, toRaw, isReactive } from '../../src' +import { effect, isReactive, reactive, toRaw } from '../../src' describe('reactivity/collections', () => { describe('Map', () => { @@ -26,6 +26,21 @@ describe('reactivity/collections', () => { expect(dummy).toBe(undefined) }) + it('should observe mutations with observed value', () => { + let dummy + const value = reactive({}) + const map = reactive(new Map()) + effect(() => { + dummy = map.get('key') + }) + + expect(dummy).toBe(undefined) + map.set('key', value) + expect(dummy).toBe(value) + map.delete('key') + expect(dummy).toBe(undefined) + }) + it('should observe size mutations', () => { let dummy const map = reactive(new Map()) diff --git a/packages/reactivity/__tests__/collections/Set.spec.ts b/packages/reactivity/__tests__/collections/Set.spec.ts index f01090d2f54..3f7107ce85a 100644 --- a/packages/reactivity/__tests__/collections/Set.spec.ts +++ b/packages/reactivity/__tests__/collections/Set.spec.ts @@ -1,4 +1,4 @@ -import { reactive, effect, isReactive, toRaw } from '../../src' +import { effect, isReactive, reactive, toRaw } from '../../src' describe('reactivity/collections', () => { describe('Set', () => { @@ -22,6 +22,19 @@ describe('reactivity/collections', () => { expect(dummy).toBe(false) }) + it('should observe mutations with observed value', () => { + let dummy + const value = reactive({}) + const set = reactive(new Set()) + effect(() => (dummy = set.has(value))) + + expect(dummy).toBe(false) + set.add(value) + expect(dummy).toBe(true) + set.delete(value) + expect(dummy).toBe(false) + }) + it('should observe for of iteration', () => { let dummy const set = reactive(new Set() as Set) diff --git a/packages/reactivity/__tests__/collections/WeakMap.spec.ts b/packages/reactivity/__tests__/collections/WeakMap.spec.ts index 6c82b82dd86..887e713b92e 100644 --- a/packages/reactivity/__tests__/collections/WeakMap.spec.ts +++ b/packages/reactivity/__tests__/collections/WeakMap.spec.ts @@ -1,4 +1,4 @@ -import { reactive, effect, toRaw, isReactive } from '../../src' +import { effect, isReactive, reactive, toRaw } from '../../src' describe('reactivity/collections', () => { describe('WeakMap', () => { @@ -27,6 +27,22 @@ describe('reactivity/collections', () => { expect(dummy).toBe(undefined) }) + it('should observe mutations with observed value', () => { + let dummy + const key = {} + const value = reactive({}) + const map = reactive(new WeakMap()) + effect(() => { + dummy = map.get(key) + }) + + expect(dummy).toBe(undefined) + map.set(key, value) + expect(dummy).toBe(value) + map.delete(key) + expect(dummy).toBe(undefined) + }) + it('should not observe custom property mutations', () => { let dummy const map: any = reactive(new WeakMap()) diff --git a/packages/reactivity/__tests__/collections/WeakSet.spec.ts b/packages/reactivity/__tests__/collections/WeakSet.spec.ts index 2427de125e5..9a8ec69334f 100644 --- a/packages/reactivity/__tests__/collections/WeakSet.spec.ts +++ b/packages/reactivity/__tests__/collections/WeakSet.spec.ts @@ -1,4 +1,4 @@ -import { reactive, isReactive, effect, toRaw } from '../../src' +import { effect, isReactive, reactive, toRaw } from '../../src' describe('reactivity/collections', () => { describe('WeakSet', () => { @@ -23,6 +23,19 @@ describe('reactivity/collections', () => { expect(dummy).toBe(false) }) + it('should observe mutations with observed value', () => { + let dummy + const value = reactive({}) + const set = reactive(new WeakSet()) + effect(() => (dummy = set.has(value))) + + expect(dummy).toBe(false) + set.add(value) + expect(dummy).toBe(true) + set.delete(value) + expect(dummy).toBe(false) + }) + it('should not observe custom property mutations', () => { let dummy const set: any = reactive(new WeakSet()) diff --git a/packages/reactivity/src/collectionHandlers.ts b/packages/reactivity/src/collectionHandlers.ts index b5289844089..c525d5559f5 100644 --- a/packages/reactivity/src/collectionHandlers.ts +++ b/packages/reactivity/src/collectionHandlers.ts @@ -1,8 +1,8 @@ -import { toRaw, reactive, readonly } from './reactive' -import { track, trigger, ITERATE_KEY } from './effect' +import { reactive, readonly, toRaw } from './reactive' +import { ITERATE_KEY, track, trigger } from './effect' import { TrackOpTypes, TriggerOpTypes } from './operations' import { LOCKED } from './lock' -import { isObject, capitalize, hasOwn, hasChanged } from '@vue/shared' +import { capitalize, hasChanged, hasOwn, isObject } from '@vue/shared' export type CollectionTypes = IterableCollections | WeakCollections @@ -87,6 +87,7 @@ 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) From 5b9628ea6732c5b9beddb576a9f345e139daef07 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 13 Jan 2020 17:07:48 -0500 Subject: [PATCH 2/2] fix: actually use observed keys in Map and WeakMap tests --- packages/reactivity/__tests__/collections/Map.spec.ts | 11 ++++++----- packages/reactivity/__tests__/collections/Set.spec.ts | 2 +- .../reactivity/__tests__/collections/WeakMap.spec.ts | 6 +++--- .../reactivity/__tests__/collections/WeakSet.spec.ts | 2 +- packages/reactivity/src/collectionHandlers.ts | 7 ++++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/reactivity/__tests__/collections/Map.spec.ts b/packages/reactivity/__tests__/collections/Map.spec.ts index cb8f0ebe34a..4cfb9e6bbcd 100644 --- a/packages/reactivity/__tests__/collections/Map.spec.ts +++ b/packages/reactivity/__tests__/collections/Map.spec.ts @@ -1,4 +1,4 @@ -import { effect, isReactive, reactive, toRaw } from '../../src' +import { reactive, effect, toRaw, isReactive } from '../../src' describe('reactivity/collections', () => { describe('Map', () => { @@ -26,18 +26,19 @@ describe('reactivity/collections', () => { expect(dummy).toBe(undefined) }) - it('should observe mutations with observed value', () => { + it('should observe mutations with observed value as key', () => { let dummy + const key = reactive({}) const value = reactive({}) const map = reactive(new Map()) effect(() => { - dummy = map.get('key') + dummy = map.get(key) }) expect(dummy).toBe(undefined) - map.set('key', value) + map.set(key, value) expect(dummy).toBe(value) - map.delete('key') + map.delete(key) expect(dummy).toBe(undefined) }) diff --git a/packages/reactivity/__tests__/collections/Set.spec.ts b/packages/reactivity/__tests__/collections/Set.spec.ts index 3f7107ce85a..9e3efa166f1 100644 --- a/packages/reactivity/__tests__/collections/Set.spec.ts +++ b/packages/reactivity/__tests__/collections/Set.spec.ts @@ -1,4 +1,4 @@ -import { effect, isReactive, reactive, toRaw } from '../../src' +import { reactive, effect, isReactive, toRaw } from '../../src' describe('reactivity/collections', () => { describe('Set', () => { diff --git a/packages/reactivity/__tests__/collections/WeakMap.spec.ts b/packages/reactivity/__tests__/collections/WeakMap.spec.ts index 887e713b92e..e3dde72e618 100644 --- a/packages/reactivity/__tests__/collections/WeakMap.spec.ts +++ b/packages/reactivity/__tests__/collections/WeakMap.spec.ts @@ -1,4 +1,4 @@ -import { effect, isReactive, reactive, toRaw } from '../../src' +import { reactive, effect, toRaw, isReactive } from '../../src' describe('reactivity/collections', () => { describe('WeakMap', () => { @@ -27,9 +27,9 @@ describe('reactivity/collections', () => { expect(dummy).toBe(undefined) }) - it('should observe mutations with observed value', () => { + it('should observe mutations with observed value as key', () => { let dummy - const key = {} + const key = reactive({}) const value = reactive({}) const map = reactive(new WeakMap()) effect(() => { diff --git a/packages/reactivity/__tests__/collections/WeakSet.spec.ts b/packages/reactivity/__tests__/collections/WeakSet.spec.ts index 9a8ec69334f..182298cf4b0 100644 --- a/packages/reactivity/__tests__/collections/WeakSet.spec.ts +++ b/packages/reactivity/__tests__/collections/WeakSet.spec.ts @@ -1,4 +1,4 @@ -import { effect, isReactive, reactive, toRaw } from '../../src' +import { reactive, isReactive, effect, toRaw } from '../../src' describe('reactivity/collections', () => { describe('WeakSet', () => { diff --git a/packages/reactivity/src/collectionHandlers.ts b/packages/reactivity/src/collectionHandlers.ts index c525d5559f5..cb90cf0e3c2 100644 --- a/packages/reactivity/src/collectionHandlers.ts +++ b/packages/reactivity/src/collectionHandlers.ts @@ -1,8 +1,8 @@ -import { reactive, readonly, toRaw } from './reactive' -import { ITERATE_KEY, track, trigger } from './effect' +import { toRaw, reactive, readonly } from './reactive' +import { track, trigger, ITERATE_KEY } from './effect' import { TrackOpTypes, TriggerOpTypes } from './operations' import { LOCKED } from './lock' -import { capitalize, hasChanged, hasOwn, isObject } from '@vue/shared' +import { isObject, capitalize, hasOwn, hasChanged } from '@vue/shared' export type CollectionTypes = IterableCollections | WeakCollections @@ -63,6 +63,7 @@ function add(this: SetTypes, value: unknown) { function set(this: MapTypes, key: unknown, value: unknown) { value = toRaw(value) + key = toRaw(key) const target = toRaw(this) const proto = getProto(target) const hadKey = proto.has.call(target, key)