import getAllKeys from './getAllKeys.js' /** Used to compose bitmasks for value comparisons. */ const COMPARE_PARTIAL_FLAG = 1 /** Used to check objects for own properties. */ const hasOwnProperty = Object.prototype.hasOwnProperty /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { const isPartial = bitmask & COMPARE_PARTIAL_FLAG const objProps = getAllKeys(object) const objLength = objProps.length const othProps = getAllKeys(other) const othLength = othProps.length if (objLength != othLength && !isPartial) { return false } let key let index = objLength while (index--) { key = objProps[index] if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false } } // Assume cyclic values are equal. const stacked = stack.get(object) if (stacked && stack.get(other)) { return stacked == other } let result = true stack.set(object, other) stack.set(other, object) let compared let skipCtor = isPartial while (++index < objLength) { key = objProps[index] const objValue = object[key] const othValue = other[key] if (customizer) { compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack) } // Recursively compare objects (susceptible to call stack limits). if (!(compared === undefined ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) : compared )) { result = false break } skipCtor || (skipCtor = key == 'constructor') } if (result && !skipCtor) { const objCtor = object.constructor const othCtor = other.constructor // Non `Object` object instances with different constructors are not equal. if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { result = false } } stack['delete'](object) stack['delete'](other) return result } export default equalObjects