fix(reactivity): account for NaN in value change checks (#361)
This commit is contained in:
parent
11d0778f9c
commit
18a349ce8c
@ -311,5 +311,13 @@ describe('reactivity/collections', () => {
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -107,5 +107,15 @@ describe('reactivity/collections', () => {
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -691,4 +691,14 @@ describe('reactivity/effect', () => {
|
||||
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)
|
||||
})
|
||||
})
|
||||
|
@ -2,7 +2,7 @@ import { reactive, readonly, toRaw } from './reactive'
|
||||
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(
|
||||
@ -52,13 +52,13 @@ function 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)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { toRaw, reactive, readonly } from './reactive'
|
||||
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
|
||||
|
||||
@ -73,13 +73,13 @@ function set(this: MapTypes, key: unknown, value: unknown) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,14 @@ import {
|
||||
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,
|
||||
@ -144,7 +151,7 @@ function doWatch(
|
||||
return
|
||||
}
|
||||
const newValue = runner()
|
||||
if (deep || newValue !== oldValue) {
|
||||
if (deep || hasChanged(newValue, oldValue)) {
|
||||
// cleanup before running cb again
|
||||
if (cleanup) {
|
||||
cleanup()
|
||||
|
@ -67,3 +67,7 @@ export const hyphenate = (str: string): string => {
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user