Skip to content

Commit fcf9b2c

Browse files
authored
fix(reactivity): should trigger collection's write-function correctly on non-reactive keys (#1992)
1 parent b2dc953 commit fcf9b2c

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

packages/reactivity/__tests__/collections/Map.spec.ts

+26-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { reactive, effect, toRaw, isReactive } from '../../src'
22

33
describe('reactivity/collections', () => {
4+
function coverCollectionFn(collection: Map<any, any>, fnName: string) {
5+
const spy = jest.fn()
6+
let proxy = reactive(collection)
7+
;(collection as any)[fnName] = spy
8+
return [proxy as any, spy]
9+
}
10+
411
describe('Map', () => {
512
test('instanceof', () => {
613
const original = new Map()
@@ -437,14 +444,27 @@ describe('reactivity/collections', () => {
437444
expect(spy).toHaveBeenCalledTimes(3)
438445
})
439446

440-
it('should trigger has only once for non-reactive keys', () => {
441-
const map = new Map()
442-
const spy = jest.fn()
443-
map.has = spy
444-
445-
let proxy = reactive(map)
447+
it('should trigger Map.has only once for non-reactive keys', () => {
448+
const [proxy, spy] = coverCollectionFn(new Map(), 'has')
446449
proxy.has('k')
450+
expect(spy).toBeCalledTimes(1)
451+
})
452+
453+
it('should trigger Map.set only once for non-reactive keys', () => {
454+
const [proxy, spy] = coverCollectionFn(new Map(), 'set')
455+
proxy.set('k', 'v')
456+
expect(spy).toBeCalledTimes(1)
457+
})
458+
459+
it('should trigger Map.delete only once for non-reactive keys', () => {
460+
const [proxy, spy] = coverCollectionFn(new Map(), 'delete')
461+
proxy.delete('foo')
462+
expect(spy).toBeCalledTimes(1)
463+
})
447464

465+
it('should trigger Map.clear only once for non-reactive keys', () => {
466+
const [proxy, spy] = coverCollectionFn(new Map(), 'clear')
467+
proxy.clear()
448468
expect(spy).toBeCalledTimes(1)
449469
})
450470
})

packages/reactivity/__tests__/collections/Set.spec.ts

+31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { reactive, effect, isReactive, toRaw } from '../../src'
22

33
describe('reactivity/collections', () => {
4+
function coverCollectionFn(collection: Set<any>, fnName: string) {
5+
const spy = jest.fn()
6+
let proxy = reactive(collection)
7+
;(collection as any)[fnName] = spy
8+
return [proxy as any, spy]
9+
}
10+
411
describe('Set', () => {
512
it('instanceof', () => {
613
const original = new Set()
@@ -423,5 +430,29 @@ describe('reactivity/collections', () => {
423430
}, thisArg)
424431
expect(count).toBe(1)
425432
})
433+
434+
it('should trigger Set.has only once for non-reactive keys', () => {
435+
const [proxy, spy] = coverCollectionFn(new Set(), 'has')
436+
proxy.has('foo')
437+
expect(spy).toBeCalledTimes(1)
438+
})
439+
440+
it('should trigger Set.add only once for non-reactive keys', () => {
441+
const [proxy, spy] = coverCollectionFn(new Set(), 'add')
442+
proxy.add('foo')
443+
expect(spy).toBeCalledTimes(1)
444+
})
445+
446+
it('should trigger Set.delete only once for non-reactive keys', () => {
447+
const [proxy, spy] = coverCollectionFn(new Set(), 'delete')
448+
proxy.delete('foo')
449+
expect(spy).toBeCalledTimes(1)
450+
})
451+
452+
it('should trigger Set.clear only once for non-reactive keys', () => {
453+
const [proxy, spy] = coverCollectionFn(new Set(), 'clear')
454+
proxy.clear()
455+
expect(spy).toBeCalledTimes(1)
456+
})
426457
})
427458
})

packages/reactivity/src/collectionHandlers.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function add(this: SetTypes, value: unknown) {
7676
const target = toRaw(this)
7777
const proto = getProto(target)
7878
const hadKey = proto.has.call(target, value)
79-
const result = proto.add.call(target, value)
79+
const result = target.add(value)
8080
if (!hadKey) {
8181
trigger(target, TriggerOpTypes.ADD, value, value)
8282
}
@@ -86,7 +86,7 @@ function add(this: SetTypes, value: unknown) {
8686
function set(this: MapTypes, key: unknown, value: unknown) {
8787
value = toRaw(value)
8888
const target = toRaw(this)
89-
const { has, get, set } = getProto(target)
89+
const { has, get } = getProto(target)
9090

9191
let hadKey = has.call(target, key)
9292
if (!hadKey) {
@@ -97,7 +97,7 @@ function set(this: MapTypes, key: unknown, value: unknown) {
9797
}
9898

9999
const oldValue = get.call(target, key)
100-
const result = set.call(target, key, value)
100+
const result = target.set(key, value)
101101
if (!hadKey) {
102102
trigger(target, TriggerOpTypes.ADD, key, value)
103103
} else if (hasChanged(value, oldValue)) {
@@ -108,7 +108,7 @@ function set(this: MapTypes, key: unknown, value: unknown) {
108108

109109
function deleteEntry(this: CollectionTypes, key: unknown) {
110110
const target = toRaw(this)
111-
const { has, get, delete: del } = getProto(target)
111+
const { has, get } = getProto(target)
112112
let hadKey = has.call(target, key)
113113
if (!hadKey) {
114114
key = toRaw(key)
@@ -119,7 +119,7 @@ function deleteEntry(this: CollectionTypes, key: unknown) {
119119

120120
const oldValue = get ? get.call(target, key) : undefined
121121
// forward the operation before queueing reactions
122-
const result = del.call(target, key)
122+
const result = target.delete(key)
123123
if (hadKey) {
124124
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
125125
}
@@ -135,7 +135,7 @@ function clear(this: IterableCollections) {
135135
: new Set(target)
136136
: undefined
137137
// forward the operation before queueing reactions
138-
const result = getProto(target).clear.call(target)
138+
const result = target.clear()
139139
if (hadItems) {
140140
trigger(target, TriggerOpTypes.CLEAR, undefined, undefined, oldTarget)
141141
}

0 commit comments

Comments
 (0)