fix(reactivity): should trigger collection's write-function correctly on non-reactive keys (#1992)
This commit is contained in:
parent
b2dc95378d
commit
fcf9b2cf19
@ -1,6 +1,13 @@
|
|||||||
import { reactive, effect, toRaw, isReactive } from '../../src'
|
import { reactive, effect, toRaw, isReactive } from '../../src'
|
||||||
|
|
||||||
describe('reactivity/collections', () => {
|
describe('reactivity/collections', () => {
|
||||||
|
function coverCollectionFn(collection: Map<any, any>, fnName: string) {
|
||||||
|
const spy = jest.fn()
|
||||||
|
let proxy = reactive(collection)
|
||||||
|
;(collection as any)[fnName] = spy
|
||||||
|
return [proxy as any, spy]
|
||||||
|
}
|
||||||
|
|
||||||
describe('Map', () => {
|
describe('Map', () => {
|
||||||
test('instanceof', () => {
|
test('instanceof', () => {
|
||||||
const original = new Map()
|
const original = new Map()
|
||||||
@ -437,14 +444,27 @@ describe('reactivity/collections', () => {
|
|||||||
expect(spy).toHaveBeenCalledTimes(3)
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger has only once for non-reactive keys', () => {
|
it('should trigger Map.has only once for non-reactive keys', () => {
|
||||||
const map = new Map()
|
const [proxy, spy] = coverCollectionFn(new Map(), 'has')
|
||||||
const spy = jest.fn()
|
|
||||||
map.has = spy
|
|
||||||
|
|
||||||
let proxy = reactive(map)
|
|
||||||
proxy.has('k')
|
proxy.has('k')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Map.set only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Map(), 'set')
|
||||||
|
proxy.set('k', 'v')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Map.delete only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Map(), 'delete')
|
||||||
|
proxy.delete('foo')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Map.clear only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Map(), 'clear')
|
||||||
|
proxy.clear()
|
||||||
expect(spy).toBeCalledTimes(1)
|
expect(spy).toBeCalledTimes(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
import { reactive, effect, isReactive, toRaw } from '../../src'
|
import { reactive, effect, isReactive, toRaw } from '../../src'
|
||||||
|
|
||||||
describe('reactivity/collections', () => {
|
describe('reactivity/collections', () => {
|
||||||
|
function coverCollectionFn(collection: Set<any>, fnName: string) {
|
||||||
|
const spy = jest.fn()
|
||||||
|
let proxy = reactive(collection)
|
||||||
|
;(collection as any)[fnName] = spy
|
||||||
|
return [proxy as any, spy]
|
||||||
|
}
|
||||||
|
|
||||||
describe('Set', () => {
|
describe('Set', () => {
|
||||||
it('instanceof', () => {
|
it('instanceof', () => {
|
||||||
const original = new Set()
|
const original = new Set()
|
||||||
@ -423,5 +430,29 @@ describe('reactivity/collections', () => {
|
|||||||
}, thisArg)
|
}, thisArg)
|
||||||
expect(count).toBe(1)
|
expect(count).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should trigger Set.has only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Set(), 'has')
|
||||||
|
proxy.has('foo')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Set.add only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Set(), 'add')
|
||||||
|
proxy.add('foo')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Set.delete only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Set(), 'delete')
|
||||||
|
proxy.delete('foo')
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger Set.clear only once for non-reactive keys', () => {
|
||||||
|
const [proxy, spy] = coverCollectionFn(new Set(), 'clear')
|
||||||
|
proxy.clear()
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -76,7 +76,7 @@ function add(this: SetTypes, value: unknown) {
|
|||||||
const target = toRaw(this)
|
const target = toRaw(this)
|
||||||
const proto = getProto(target)
|
const proto = getProto(target)
|
||||||
const hadKey = proto.has.call(target, value)
|
const hadKey = proto.has.call(target, value)
|
||||||
const result = proto.add.call(target, value)
|
const result = target.add(value)
|
||||||
if (!hadKey) {
|
if (!hadKey) {
|
||||||
trigger(target, TriggerOpTypes.ADD, value, value)
|
trigger(target, TriggerOpTypes.ADD, value, value)
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ function add(this: SetTypes, value: unknown) {
|
|||||||
function set(this: MapTypes, key: unknown, value: unknown) {
|
function set(this: MapTypes, key: unknown, value: unknown) {
|
||||||
value = toRaw(value)
|
value = toRaw(value)
|
||||||
const target = toRaw(this)
|
const target = toRaw(this)
|
||||||
const { has, get, set } = getProto(target)
|
const { has, get } = getProto(target)
|
||||||
|
|
||||||
let hadKey = has.call(target, key)
|
let hadKey = has.call(target, key)
|
||||||
if (!hadKey) {
|
if (!hadKey) {
|
||||||
@ -97,7 +97,7 @@ function set(this: MapTypes, key: unknown, value: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const oldValue = get.call(target, key)
|
const oldValue = get.call(target, key)
|
||||||
const result = set.call(target, key, value)
|
const result = target.set(key, value)
|
||||||
if (!hadKey) {
|
if (!hadKey) {
|
||||||
trigger(target, TriggerOpTypes.ADD, key, value)
|
trigger(target, TriggerOpTypes.ADD, key, value)
|
||||||
} else if (hasChanged(value, oldValue)) {
|
} else if (hasChanged(value, oldValue)) {
|
||||||
@ -108,7 +108,7 @@ function set(this: MapTypes, key: unknown, value: unknown) {
|
|||||||
|
|
||||||
function deleteEntry(this: CollectionTypes, key: unknown) {
|
function deleteEntry(this: CollectionTypes, key: unknown) {
|
||||||
const target = toRaw(this)
|
const target = toRaw(this)
|
||||||
const { has, get, delete: del } = getProto(target)
|
const { has, get } = getProto(target)
|
||||||
let hadKey = has.call(target, key)
|
let hadKey = has.call(target, key)
|
||||||
if (!hadKey) {
|
if (!hadKey) {
|
||||||
key = toRaw(key)
|
key = toRaw(key)
|
||||||
@ -119,7 +119,7 @@ function deleteEntry(this: CollectionTypes, key: unknown) {
|
|||||||
|
|
||||||
const oldValue = get ? get.call(target, key) : undefined
|
const oldValue = get ? get.call(target, key) : undefined
|
||||||
// forward the operation before queueing reactions
|
// forward the operation before queueing reactions
|
||||||
const result = del.call(target, key)
|
const result = target.delete(key)
|
||||||
if (hadKey) {
|
if (hadKey) {
|
||||||
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
|
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ function clear(this: IterableCollections) {
|
|||||||
: new Set(target)
|
: new Set(target)
|
||||||
: undefined
|
: undefined
|
||||||
// forward the operation before queueing reactions
|
// forward the operation before queueing reactions
|
||||||
const result = getProto(target).clear.call(target)
|
const result = target.clear()
|
||||||
if (hadItems) {
|
if (hadItems) {
|
||||||
trigger(target, TriggerOpTypes.CLEAR, undefined, undefined, oldTarget)
|
trigger(target, TriggerOpTypes.CLEAR, undefined, undefined, oldTarget)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user