123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- var _a = Object.prototype, toString = _a.toString, hasOwnProperty = _a.hasOwnProperty;
- var previousComparisons = new Map();
- /**
- * Performs a deep equality check on two JavaScript values, tolerating cycles.
- */
- function equal(a, b) {
- try {
- return check(a, b);
- }
- finally {
- previousComparisons.clear();
- }
- }
- function check(a, b) {
- // If the two values are strictly equal, our job is easy.
- if (a === b) {
- return true;
- }
- // Object.prototype.toString returns a representation of the runtime type of
- // the given value that is considerably more precise than typeof.
- var aTag = toString.call(a);
- var bTag = toString.call(b);
- // If the runtime types of a and b are different, they could maybe be equal
- // under some interpretation of equality, but for simplicity and performance
- // we just return false instead.
- if (aTag !== bTag) {
- return false;
- }
- switch (aTag) {
- case '[object Array]':
- // Arrays are a lot like other objects, but we can cheaply compare their
- // lengths as a short-cut before comparing their elements.
- if (a.length !== b.length)
- return false;
- // Fall through to object case...
- case '[object Object]': {
- if (previouslyCompared(a, b))
- return true;
- var aKeys = Object.keys(a);
- var bKeys = Object.keys(b);
- // If `a` and `b` have a different number of enumerable keys, they
- // must be different.
- var keyCount = aKeys.length;
- if (keyCount !== bKeys.length)
- return false;
- // Now make sure they have the same keys.
- for (var k = 0; k < keyCount; ++k) {
- if (!hasOwnProperty.call(b, aKeys[k])) {
- return false;
- }
- }
- // Finally, check deep equality of all child properties.
- for (var k = 0; k < keyCount; ++k) {
- var key = aKeys[k];
- if (!check(a[key], b[key])) {
- return false;
- }
- }
- return true;
- }
- case '[object Error]':
- return a.name === b.name && a.message === b.message;
- case '[object Number]':
- // Handle NaN, which is !== itself.
- if (a !== a)
- return b !== b;
- // Fall through to shared +a === +b case...
- case '[object Boolean]':
- case '[object Date]':
- return +a === +b;
- case '[object RegExp]':
- case '[object String]':
- return a == "" + b;
- case '[object Map]':
- case '[object Set]': {
- if (a.size !== b.size)
- return false;
- if (previouslyCompared(a, b))
- return true;
- var aIterator = a.entries();
- var isMap = aTag === '[object Map]';
- while (true) {
- var info = aIterator.next();
- if (info.done)
- break;
- // If a instanceof Set, aValue === aKey.
- var _a = info.value, aKey = _a[0], aValue = _a[1];
- // So this works the same way for both Set and Map.
- if (!b.has(aKey)) {
- return false;
- }
- // However, we care about deep equality of values only when dealing
- // with Map structures.
- if (isMap && !check(aValue, b.get(aKey))) {
- return false;
- }
- }
- return true;
- }
- }
- // Otherwise the values are not equal.
- return false;
- }
- function previouslyCompared(a, b) {
- // Though cyclic references can make an object graph appear infinite from the
- // perspective of a depth-first traversal, the graph still contains a finite
- // number of distinct object references. We use the previousComparisons cache
- // to avoid comparing the same pair of object references more than once, which
- // guarantees termination (even if we end up comparing every object in one
- // graph to every object in the other graph, which is extremely unlikely),
- // while still allowing weird isomorphic structures (like rings with different
- // lengths) a chance to pass the equality test.
- var bSet = previousComparisons.get(a);
- if (bSet) {
- // Return true here because we can be sure false will be returned somewhere
- // else if the objects are not equivalent.
- if (bSet.has(b))
- return true;
- }
- else {
- previousComparisons.set(a, bSet = new Set);
- }
- bSet.add(b);
- return false;
- }
- export default equal;
- export { equal };
- //# sourceMappingURL=equality.esm.js.map
|