Skip to content

Commit

Permalink
refactor: ensure stack
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Nov 4, 2024
1 parent 3fba30d commit b070eab
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 23 deletions.
51 changes: 32 additions & 19 deletions src/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,10 @@ export function isNonEmptyArray(val: unknown): val is Array<any> {
}

export function isEqualWith(value: any, other: any, fn: (value: any, other: any) => any): boolean {
const cache = new WeakMap()
const valueStack = new WeakMap()
const otherStack = new WeakMap()

function baseIsEqual(value: any, other: any, cache: WeakMap<any, any>): boolean {
function baseIsEqual(value: any, other: any, valueStack: WeakMap<any, any>, otherStack: WeakMap<any, any>): boolean {
const customEqual = fn(value, other)

if (customEqual === true) {
Expand All @@ -195,6 +196,16 @@ export function isEqualWith(value: any, other: any, fn: (value: any, other: any)
return false
}

if (
(toRawType(value) === 'String' && toRawType(other) === 'String') ||
(toRawType(value) === 'Number' && toRawType(other) === 'Number') ||
(toRawType(value) === 'Boolean' && toRawType(other) === 'Boolean') ||
(toRawType(value) === 'BigInt' && toRawType(other) === 'BigInt') ||
(toRawType(value) === 'Symbol' && toRawType(other) === 'Symbol')
) {
return value.valueOf() === other.valueOf()
}

if (isDate(value) && isDate(other)) {
return value.getTime() === other.getTime()
}
Expand Down Expand Up @@ -233,12 +244,12 @@ export function isEqualWith(value: any, other: any, fn: (value: any, other: any)
return valueTypedArray.every((v, i) => v === otherTypedArray[i])
}

if (cache.get(value) === other && cache.get(other) === value) {
if (valueStack.get(value) === other && otherStack.get(other) === value) {
return true
}

cache.set(value, other)
cache.set(other, value)
valueStack.set(value, other)
otherStack.set(other, value)

if ((isMap(value) && isMap(other)) || (isSet(value) && isSet(other))) {
if (value.size !== other.size) {
Expand All @@ -247,26 +258,23 @@ export function isEqualWith(value: any, other: any, fn: (value: any, other: any)

const valueArray = [...value]
const otherArray = [...other]
const result = valueArray.every((v, i) => baseIsEqual(v, otherArray[i], valueStack, otherStack))
valueStack.delete(value)
otherStack.delete(other)

return valueArray.every((v, i) => baseIsEqual(v, otherArray[i], cache))
return result
}

if (isArray(value) && isArray(other)) {
if (value.length !== other.length) {
return false
}

return value.every((v, i) => baseIsEqual(v, other[i], cache))
}
const result = value.every((v, i) => baseIsEqual(v, other[i], valueStack, otherStack))
valueStack.delete(value)
otherStack.delete(other)

if (
(toRawType(value) === 'String' && toRawType(other) === 'String') ||
(toRawType(value) === 'Number' && toRawType(other) === 'Number') ||
(toRawType(value) === 'Boolean' && toRawType(other) === 'Boolean') ||
(toRawType(value) === 'BigInt' && toRawType(other) === 'BigInt') ||
(toRawType(value) === 'Symbol' && toRawType(other) === 'Symbol')
) {
return value.valueOf() === other.valueOf()
return result
}

if (isPlainObject(value) && isPlainObject(other)) {
Expand All @@ -277,15 +285,20 @@ export function isEqualWith(value: any, other: any, fn: (value: any, other: any)
return false
}

return valueOwnKeys.every((k) =>
baseIsEqual(value[k as keyof typeof value], other[k as keyof typeof other], cache),
const result = valueOwnKeys.every((k) =>
baseIsEqual(value[k as keyof typeof value], other[k as keyof typeof other], valueStack, otherStack),
)

valueStack.delete(value)
otherStack.delete(other)

return result
}

return false
}

return baseIsEqual(value, other, cache)
return baseIsEqual(value, other, valueStack, otherStack)
}

export function isEqual(value: any, other: any): boolean {
Expand Down
10 changes: 6 additions & 4 deletions tests/general.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,14 @@ it('isEqual', () => {

const a: Record<string, any> = { n: 1 }
a.self = a
const b: Record<string, any> = { n: 1 }
b.self = b
a.x = b
b.x = a
const b: Record<string, any> = { n: 1, self: { n: 1 } }
b.self.self = a

const c = [a, b]
const d = [b, a]

expect(isEqual(a, b)).toBe(true)
expect(isEqual(c, d)).toBe(true)
})

it('isEqualWith', () => {
Expand Down

0 comments on commit b070eab

Please sign in to comment.