_equals.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import _arrayFromIterator from "./_arrayFromIterator.js";
  2. import _includesWith from "./_includesWith.js";
  3. import _functionName from "./_functionName.js";
  4. import _has from "./_has.js";
  5. import _objectIs from "./_objectIs.js";
  6. import keys from "../keys.js";
  7. import type from "../type.js";
  8. /**
  9. * private _uniqContentEquals function.
  10. * That function is checking equality of 2 iterator contents with 2 assumptions
  11. * - iterators lengths are the same
  12. * - iterators values are unique
  13. *
  14. * false-positive result will be returned for comparison of, e.g.
  15. * - [1,2,3] and [1,2,3,4]
  16. * - [1,1,1] and [1,2,3]
  17. * */
  18. function _uniqContentEquals(aIterator, bIterator, stackA, stackB) {
  19. var a = _arrayFromIterator(aIterator);
  20. var b = _arrayFromIterator(bIterator);
  21. function eq(_a, _b) {
  22. return _equals(_a, _b, stackA.slice(), stackB.slice());
  23. } // if *a* array contains any element that is not included in *b*
  24. return !_includesWith(function (b, aItem) {
  25. return !_includesWith(eq, aItem, b);
  26. }, b, a);
  27. }
  28. export default function _equals(a, b, stackA, stackB) {
  29. if (_objectIs(a, b)) {
  30. return true;
  31. }
  32. var typeA = type(a);
  33. if (typeA !== type(b)) {
  34. return false;
  35. }
  36. if (typeof a['fantasy-land/equals'] === 'function' || typeof b['fantasy-land/equals'] === 'function') {
  37. return typeof a['fantasy-land/equals'] === 'function' && a['fantasy-land/equals'](b) && typeof b['fantasy-land/equals'] === 'function' && b['fantasy-land/equals'](a);
  38. }
  39. if (typeof a.equals === 'function' || typeof b.equals === 'function') {
  40. return typeof a.equals === 'function' && a.equals(b) && typeof b.equals === 'function' && b.equals(a);
  41. }
  42. switch (typeA) {
  43. case 'Arguments':
  44. case 'Array':
  45. case 'Object':
  46. if (typeof a.constructor === 'function' && _functionName(a.constructor) === 'Promise') {
  47. return a === b;
  48. }
  49. break;
  50. case 'Boolean':
  51. case 'Number':
  52. case 'String':
  53. if (!(typeof a === typeof b && _objectIs(a.valueOf(), b.valueOf()))) {
  54. return false;
  55. }
  56. break;
  57. case 'Date':
  58. if (!_objectIs(a.valueOf(), b.valueOf())) {
  59. return false;
  60. }
  61. break;
  62. case 'Error':
  63. return a.name === b.name && a.message === b.message;
  64. case 'RegExp':
  65. if (!(a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.sticky === b.sticky && a.unicode === b.unicode)) {
  66. return false;
  67. }
  68. break;
  69. }
  70. var idx = stackA.length - 1;
  71. while (idx >= 0) {
  72. if (stackA[idx] === a) {
  73. return stackB[idx] === b;
  74. }
  75. idx -= 1;
  76. }
  77. switch (typeA) {
  78. case 'Map':
  79. if (a.size !== b.size) {
  80. return false;
  81. }
  82. return _uniqContentEquals(a.entries(), b.entries(), stackA.concat([a]), stackB.concat([b]));
  83. case 'Set':
  84. if (a.size !== b.size) {
  85. return false;
  86. }
  87. return _uniqContentEquals(a.values(), b.values(), stackA.concat([a]), stackB.concat([b]));
  88. case 'Arguments':
  89. case 'Array':
  90. case 'Object':
  91. case 'Boolean':
  92. case 'Number':
  93. case 'String':
  94. case 'Date':
  95. case 'Error':
  96. case 'RegExp':
  97. case 'Int8Array':
  98. case 'Uint8Array':
  99. case 'Uint8ClampedArray':
  100. case 'Int16Array':
  101. case 'Uint16Array':
  102. case 'Int32Array':
  103. case 'Uint32Array':
  104. case 'Float32Array':
  105. case 'Float64Array':
  106. case 'ArrayBuffer':
  107. break;
  108. default:
  109. // Values of other types are only equal if identical.
  110. return false;
  111. }
  112. var keysA = keys(a);
  113. if (keysA.length !== keys(b).length) {
  114. return false;
  115. }
  116. var extendedStackA = stackA.concat([a]);
  117. var extendedStackB = stackB.concat([b]);
  118. idx = keysA.length - 1;
  119. while (idx >= 0) {
  120. var key = keysA[idx];
  121. if (!(_has(key, b) && _equals(b[key], a[key], extendedStackA, extendedStackB))) {
  122. return false;
  123. }
  124. idx -= 1;
  125. }
  126. return true;
  127. }