equality.esm.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. var _a = Object.prototype, toString = _a.toString, hasOwnProperty = _a.hasOwnProperty;
  2. var previousComparisons = new Map();
  3. /**
  4. * Performs a deep equality check on two JavaScript values, tolerating cycles.
  5. */
  6. function equal(a, b) {
  7. try {
  8. return check(a, b);
  9. }
  10. finally {
  11. previousComparisons.clear();
  12. }
  13. }
  14. function check(a, b) {
  15. // If the two values are strictly equal, our job is easy.
  16. if (a === b) {
  17. return true;
  18. }
  19. // Object.prototype.toString returns a representation of the runtime type of
  20. // the given value that is considerably more precise than typeof.
  21. var aTag = toString.call(a);
  22. var bTag = toString.call(b);
  23. // If the runtime types of a and b are different, they could maybe be equal
  24. // under some interpretation of equality, but for simplicity and performance
  25. // we just return false instead.
  26. if (aTag !== bTag) {
  27. return false;
  28. }
  29. switch (aTag) {
  30. case '[object Array]':
  31. // Arrays are a lot like other objects, but we can cheaply compare their
  32. // lengths as a short-cut before comparing their elements.
  33. if (a.length !== b.length)
  34. return false;
  35. // Fall through to object case...
  36. case '[object Object]': {
  37. if (previouslyCompared(a, b))
  38. return true;
  39. var aKeys = Object.keys(a);
  40. var bKeys = Object.keys(b);
  41. // If `a` and `b` have a different number of enumerable keys, they
  42. // must be different.
  43. var keyCount = aKeys.length;
  44. if (keyCount !== bKeys.length)
  45. return false;
  46. // Now make sure they have the same keys.
  47. for (var k = 0; k < keyCount; ++k) {
  48. if (!hasOwnProperty.call(b, aKeys[k])) {
  49. return false;
  50. }
  51. }
  52. // Finally, check deep equality of all child properties.
  53. for (var k = 0; k < keyCount; ++k) {
  54. var key = aKeys[k];
  55. if (!check(a[key], b[key])) {
  56. return false;
  57. }
  58. }
  59. return true;
  60. }
  61. case '[object Error]':
  62. return a.name === b.name && a.message === b.message;
  63. case '[object Number]':
  64. // Handle NaN, which is !== itself.
  65. if (a !== a)
  66. return b !== b;
  67. // Fall through to shared +a === +b case...
  68. case '[object Boolean]':
  69. case '[object Date]':
  70. return +a === +b;
  71. case '[object RegExp]':
  72. case '[object String]':
  73. return a == "" + b;
  74. case '[object Map]':
  75. case '[object Set]': {
  76. if (a.size !== b.size)
  77. return false;
  78. if (previouslyCompared(a, b))
  79. return true;
  80. var aIterator = a.entries();
  81. var isMap = aTag === '[object Map]';
  82. while (true) {
  83. var info = aIterator.next();
  84. if (info.done)
  85. break;
  86. // If a instanceof Set, aValue === aKey.
  87. var _a = info.value, aKey = _a[0], aValue = _a[1];
  88. // So this works the same way for both Set and Map.
  89. if (!b.has(aKey)) {
  90. return false;
  91. }
  92. // However, we care about deep equality of values only when dealing
  93. // with Map structures.
  94. if (isMap && !check(aValue, b.get(aKey))) {
  95. return false;
  96. }
  97. }
  98. return true;
  99. }
  100. }
  101. // Otherwise the values are not equal.
  102. return false;
  103. }
  104. function previouslyCompared(a, b) {
  105. // Though cyclic references can make an object graph appear infinite from the
  106. // perspective of a depth-first traversal, the graph still contains a finite
  107. // number of distinct object references. We use the previousComparisons cache
  108. // to avoid comparing the same pair of object references more than once, which
  109. // guarantees termination (even if we end up comparing every object in one
  110. // graph to every object in the other graph, which is extremely unlikely),
  111. // while still allowing weird isomorphic structures (like rings with different
  112. // lengths) a chance to pass the equality test.
  113. var bSet = previousComparisons.get(a);
  114. if (bSet) {
  115. // Return true here because we can be sure false will be returned somewhere
  116. // else if the objects are not equivalent.
  117. if (bSet.has(b))
  118. return true;
  119. }
  120. else {
  121. previousComparisons.set(a, bSet = new Set);
  122. }
  123. bSet.add(b);
  124. return false;
  125. }
  126. export default equal;
  127. export { equal };
  128. //# sourceMappingURL=equality.esm.js.map