quivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. return objEquiv(a, b); } /** * Tests to see if an object is a particular instance of the given type. * * @param {object} object * @param {string} type */ function instanceOf(object, type) { return Object.prototype.toString.call(object) == "[object " + type + "]"; } /** * Checks is see if the value is undefined or null. * * @param {any} value */ function isUndefinedOrNull(value) { return value === null || value === undefined; } /** * Checks to see if the object is an arguments object. * * @param {object} object */ function isArguments(object) { return instanceOf(object, "Arguments"); } /** * Compares objects for equivalence. * * @param {object} a * @param {object} b * @returns {boolean} */ function objEquiv(a, b) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) { return false; } // An identical 'prototype' property. if ((a.prototype || undefined) != (b.prototype || undefined)) { return false; } // Check for ArrayBuffer equality if (instanceOf(a, "ArrayBuffer") && instanceOf(b, "ArrayBuffer")) { if (a.byteLength !== b.byteLength) { return false; } const viewA = new Uint8Array(a); const viewB = new Uint8Array(b); for (let i = 0; i < viewA.length; i++) { if (viewA[i] !== viewB[i]) { return false; } } return true; } // Object.keys may be broken through screwy arguments passing. Converting to // an array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } let ka, kb; try { ka = Object.keys(a); kb = Object.keys(b); } catch (e) { // Happens when one is a string literal and the other isn't return false; } // Having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) { return false; } // The same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); // Equivalent values for every corresponding key, and possibly expensive deep // test for (let key of ka) { if (!_deepEqual(a[key], b[key])) { return false; } } return true; } // ... End of previously MIT-licensed code. PK