fix(v-model): handle more edge cases in looseEqual() (#379)
This commit is contained in:
@@ -56,6 +56,7 @@ export const hasOwn = (
|
||||
): key is keyof typeof val => hasOwnProperty.call(val, key)
|
||||
|
||||
export const isArray = Array.isArray
|
||||
export const isDate = (val: unknown): val is Date => val instanceof Date
|
||||
export const isFunction = (val: unknown): val is Function =>
|
||||
typeof val === 'function'
|
||||
export const isString = (val: unknown): val is string => typeof val === 'string'
|
||||
|
||||
@@ -1,40 +1,51 @@
|
||||
import { isObject, isArray } from './'
|
||||
import { isArray, isDate, isObject } from './'
|
||||
|
||||
function looseCompareArrays(a: any[], b: any[]) {
|
||||
if (a.length !== b.length) return false
|
||||
let equal = true
|
||||
for (let i = 0; equal && i < a.length; i++) {
|
||||
equal = looseEqual(a[i], b[i])
|
||||
}
|
||||
return equal
|
||||
}
|
||||
|
||||
export function looseEqual(a: any, b: any): boolean {
|
||||
if (a === b) return true
|
||||
const isObjectA = isObject(a)
|
||||
const isObjectB = isObject(b)
|
||||
if (isObjectA && isObjectB) {
|
||||
try {
|
||||
const isArrayA = isArray(a)
|
||||
const isArrayB = isArray(b)
|
||||
if (isArrayA && isArrayB) {
|
||||
return (
|
||||
a.length === b.length &&
|
||||
a.every((e: any, i: any) => looseEqual(e, b[i]))
|
||||
)
|
||||
} else if (a instanceof Date && b instanceof Date) {
|
||||
return a.getTime() === b.getTime()
|
||||
} else if (!isArrayA && !isArrayB) {
|
||||
const keysA = Object.keys(a)
|
||||
const keysB = Object.keys(b)
|
||||
return (
|
||||
keysA.length === keysB.length &&
|
||||
keysA.every(key => looseEqual(a[key], b[key]))
|
||||
)
|
||||
} else {
|
||||
/* istanbul ignore next */
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
let aValidType = isDate(a)
|
||||
let bValidType = isDate(b)
|
||||
if (aValidType || bValidType) {
|
||||
return aValidType && bValidType ? a.getTime() === b.getTime() : false
|
||||
}
|
||||
aValidType = isArray(a)
|
||||
bValidType = isArray(b)
|
||||
if (aValidType || bValidType) {
|
||||
return aValidType && bValidType ? looseCompareArrays(a, b) : false
|
||||
}
|
||||
aValidType = isObject(a)
|
||||
bValidType = isObject(b)
|
||||
if (aValidType || bValidType) {
|
||||
/* istanbul ignore if: this if will probably never be called */
|
||||
if (!aValidType || !bValidType) {
|
||||
return false
|
||||
}
|
||||
} else if (!isObjectA && !isObjectB) {
|
||||
return String(a) === String(b)
|
||||
} else {
|
||||
return false
|
||||
const aKeysCount = Object.keys(a).length
|
||||
const bKeysCount = Object.keys(b).length
|
||||
if (aKeysCount !== bKeysCount) {
|
||||
return false
|
||||
}
|
||||
for (const key in a) {
|
||||
const aHasKey = a.hasOwnProperty(key)
|
||||
const bHasKey = b.hasOwnProperty(key)
|
||||
if (
|
||||
(aHasKey && !bHasKey) ||
|
||||
(!aHasKey && bHasKey) ||
|
||||
!looseEqual(a[key], b[key])
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return String(a) === String(b)
|
||||
}
|
||||
|
||||
export function looseIndexOf(arr: any[], val: any): number {
|
||||
|
||||
Reference in New Issue
Block a user