| 28 | } |
| 29 | |
| 30 | export function isObjectEqual(objA, objB, ignoreFunction = true) { |
| 31 | if (objA === objB) return true; |
| 32 | if (objA === null && objB === null) return true; |
| 33 | if (objA === null || objB === null) return false; |
| 34 | if (typeof objA !== 'object' || typeof objB !== 'object') return false; |
| 35 | |
| 36 | const keysA = Object.keys(objA); |
| 37 | const keysB = Object.keys(objB); |
| 38 | if (keysA.length !== keysB.length) return false; |
| 39 | |
| 40 | for (let i = 0; i < keysA.length; i++) { |
| 41 | const key = keysA[i]; |
| 42 | |
| 43 | if (key === '_owner' && objA.$$typeof) { |
| 44 | // React-specific: avoid traversing React elements' _owner. |
| 45 | // _owner contains circular references |
| 46 | // and is not needed when comparing the actual elements (and not their owners) |
| 47 | continue; |
| 48 | } |
| 49 | |
| 50 | const valueA = objA[key]; |
| 51 | const valueB = objB[key]; |
| 52 | const valueAType = typeof valueA; |
| 53 | |
| 54 | if (valueAType !== typeof valueB) return false; |
| 55 | if (valueAType === 'function' && ignoreFunction) continue; |
| 56 | if (valueAType === 'object') { |
| 57 | if (!isObjectEqual(valueA, valueB, ignoreFunction)) return false; |
| 58 | else continue; |
| 59 | } |
| 60 | if (valueA !== valueB) return false; |
| 61 | } |
| 62 | return true; |
| 63 | } |
| 64 | |
| 65 | export function callOrReturn(funcOrValue, ...args) { |
| 66 | return typeof funcOrValue === 'function' ? funcOrValue(...args) : funcOrValue; |