map.get(key)!.foo++
expect(dummy).toBe(2)
})
+
+ it('should not be trigger when the value and the old value both are NaN', () => {
+ const map = reactive(new Map([['foo', NaN]]))
+ const mapSpy = jest.fn(() => map.get('foo'))
+ effect(mapSpy)
+ map.set('foo', NaN)
+ expect(mapSpy).toHaveBeenCalledTimes(1)
+ })
})
})
observed.get(key).a = 2
expect(dummy).toBe(2)
})
+
+ it('should not be trigger when the value and the old value both are NaN', () => {
+ const map = new WeakMap()
+ const key = {}
+ map.set(key, NaN)
+ const mapSpy = jest.fn(() => map.get(key))
+ effect(mapSpy)
+ map.set(key, NaN)
+ expect(mapSpy).toHaveBeenCalledTimes(1)
+ })
})
})
obj.foo = { prop: 1 }
expect(dummy).toBe(1)
})
+
+ it('should not be trigger when the value and the old value both are NaN', () => {
+ const obj = reactive({
+ foo: NaN
+ })
+ const fnSpy = jest.fn(() => obj.foo)
+ effect(fnSpy)
+ obj.foo = NaN
+ expect(fnSpy).toHaveBeenCalledTimes(1)
+ })
})
import { OperationTypes } from './operations'
import { track, trigger } from './effect'
import { LOCKED } from './lock'
-import { isObject, hasOwn, isSymbol } from '@vue/shared'
+import { isObject, hasOwn, isSymbol, hasChanged } from '@vue/shared'
import { isRef } from './ref'
const builtInSymbols = new Set(
const extraInfo = { oldValue, newValue: value }
if (!hadKey) {
trigger(target, OperationTypes.ADD, key, extraInfo)
- } else if (value !== oldValue) {
+ } else if (hasChanged(value, oldValue)) {
trigger(target, OperationTypes.SET, key, extraInfo)
}
} else {
if (!hadKey) {
trigger(target, OperationTypes.ADD, key)
- } else if (value !== oldValue) {
+ } else if (hasChanged(value, oldValue)) {
trigger(target, OperationTypes.SET, key)
}
}
import { track, trigger } from './effect'
import { OperationTypes } from './operations'
import { LOCKED } from './lock'
-import { isObject, capitalize, hasOwn } from '@vue/shared'
+import { isObject, capitalize, hasOwn, hasChanged } from '@vue/shared'
export type CollectionTypes = IterableCollections | WeakCollections
const extraInfo = { oldValue, newValue: value }
if (!hadKey) {
trigger(target, OperationTypes.ADD, key, extraInfo)
- } else if (value !== oldValue) {
+ } else if (hasChanged(value, oldValue)) {
trigger(target, OperationTypes.SET, key, extraInfo)
}
} else {
if (!hadKey) {
trigger(target, OperationTypes.ADD, key)
- } else if (value !== oldValue) {
+ } else if (hasChanged(value, oldValue)) {
trigger(target, OperationTypes.SET, key)
}
}
ReactiveEffectOptions
} from '@vue/reactivity'
import { queueJob } from './scheduler'
-import { EMPTY_OBJ, isObject, isArray, isFunction, isString } from '@vue/shared'
+import {
+ EMPTY_OBJ,
+ isObject,
+ isArray,
+ isFunction,
+ isString,
+ hasChanged
+} from '@vue/shared'
import { recordEffect } from './apiReactivity'
import {
currentInstance,
return
}
const newValue = runner()
- if (deep || newValue !== oldValue) {
+ if (deep || hasChanged(newValue, oldValue)) {
// cleanup before running cb again
if (cleanup) {
cleanup()
export const capitalize = (str: string): string => {
return str.charAt(0).toUpperCase() + str.slice(1)
}
+
+// compare whether a value has changed, accounting for NaN.
+export const hasChanged = (value: any, oldValue: any): boolean =>
+ value !== oldValue && (value === value || oldValue === oldValue)