Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 37 additions & 30 deletions packages/query-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ export function partialMatchKey(a: any, b: any): boolean {
return false
}

const hasOwn = Object.prototype.hasOwnProperty

/**
* This function returns `a` if `b` is deeply equal.
* If not, it will replace any deeply equal children of `b` with those of `a`.
Expand All @@ -258,37 +260,43 @@ export function replaceEqualDeep(a: any, b: any): any {

const array = isPlainArray(a) && isPlainArray(b)

if (array || (isPlainObject(a) && isPlainObject(b))) {
const aItems = array ? a : Object.keys(a)
const aSize = aItems.length
const bItems = array ? b : Object.keys(b)
const bSize = bItems.length
const copy: any = array ? [] : {}
const aItemsSet = new Set(aItems)

let equalItems = 0

for (let i = 0; i < bSize; i++) {
const key = array ? i : bItems[i]
if (
((!array && aItemsSet.has(key)) || array) &&
a[key] === undefined &&
b[key] === undefined
) {
copy[key] = undefined
equalItems++
} else {
copy[key] = replaceEqualDeep(a[key], b[key])
if (copy[key] === a[key] && a[key] !== undefined) {
equalItems++
}
}
if (!array && !(isPlainObject(a) && isPlainObject(b))) return b

const aItems = array ? a : Object.keys(a)
const aSize = aItems.length
const bItems = array ? b : Object.keys(b)
const bSize = bItems.length
const copy: any = array ? new Array(bSize) : {}

let equalItems = 0

for (let i = 0; i < bSize; i++) {
const key: any = array ? i : bItems[i]
const aItem = a[key]
const bItem = b[key]

if (aItem === bItem) {
copy[key] = aItem
if (array ? i < aSize : hasOwn.call(a, key)) equalItems++
continue
}

if (
aItem === null ||
bItem === null ||
typeof aItem !== 'object' ||
typeof bItem !== 'object'
) {
copy[key] = bItem
continue
}

return aSize === bSize && equalItems === aSize ? a : copy
const v = replaceEqualDeep(aItem, bItem)
copy[key] = v
if (v === aItem) equalItems++
}

return b
return aSize === bSize && equalItems === aSize ? a : copy
}

/**
Expand All @@ -311,13 +319,12 @@ export function shallowEqualObjects<T extends Record<string, any>>(
return true
}

export function isPlainArray(value: unknown) {
export function isPlainArray(value: unknown): value is Array<unknown> {
return Array.isArray(value) && value.length === Object.keys(value).length
}

// Copied from: https://github.com/jonschlinkert/is-plain-object
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
export function isPlainObject(o: any): o is Object {
export function isPlainObject(o: any): o is Record<PropertyKey, unknown> {
if (!hasObjectPrototype(o)) {
return false
}
Expand Down
Loading