fast-equals 3.0.1 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,119 +2,193 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var HAS_WEAKSET_SUPPORT = typeof WeakSet === 'function';
6
- var keys = Object.keys;
7
5
  /**
8
- * are the values passed strictly equal or both NaN
9
- *
10
- * @param a the value to compare against
11
- * @param b the value to test
12
- * @returns are the values equal by the SameValueZero principle
6
+ * Default equality comparator pass-through, used as the standard `isEqual` creator for
7
+ * use inside the built comparator.
13
8
  */
14
- function sameValueZeroEqual(a, b) {
15
- return a === b || (a !== a && b !== b);
9
+ function createDefaultIsNestedEqual(comparator) {
10
+ return function isEqual(a, b, indexOrKeyA, indexOrKeyB, parentA, parentB, meta) {
11
+ return comparator(a, b, meta);
12
+ };
16
13
  }
17
14
  /**
18
- * is the value a plain object
19
- *
20
- * @param value the value to test
21
- * @returns is the value a plain object
15
+ * Wrap the provided `areItemsEqual` method to manage the circular cache, allowing
16
+ * for circular references to be safely included in the comparison without creating
17
+ * stack overflows.
22
18
  */
23
- function isPlainObject(value) {
24
- return value.constructor === Object || value.constructor == null;
19
+ function createIsCircular(areItemsEqual) {
20
+ return function isCircular(a, b, isEqual, cache) {
21
+ if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
22
+ return areItemsEqual(a, b, isEqual, cache);
23
+ }
24
+ var cachedA = cache.get(a);
25
+ var cachedB = cache.get(b);
26
+ if (cachedA && cachedB) {
27
+ return cachedA === b && cachedB === a;
28
+ }
29
+ cache.set(a, b);
30
+ cache.set(b, a);
31
+ var result = areItemsEqual(a, b, isEqual, cache);
32
+ cache.delete(a);
33
+ cache.delete(b);
34
+ return result;
35
+ };
25
36
  }
26
37
  /**
27
- * is the value promise-like (meaning it is thenable)
38
+ * Targeted shallow merge of two objects.
28
39
  *
29
- * @param value the value to test
30
- * @returns is the value promise-like
40
+ * @NOTE
41
+ * This exists as a tinier compiled version of the `__assign` helper that
42
+ * `tsc` injects in case of `Object.assign` not being present.
31
43
  */
32
- function isPromiseLike(value) {
33
- return !!value && typeof value.then === 'function';
44
+ function merge(a, b) {
45
+ var merged = {};
46
+ for (var key in a) {
47
+ merged[key] = a[key];
48
+ }
49
+ for (var key in b) {
50
+ merged[key] = b[key];
51
+ }
52
+ return merged;
34
53
  }
35
54
  /**
36
- * is the value passed a react element
55
+ * Whether the value is a plain object.
37
56
  *
38
- * @param value the value to test
39
- * @returns is the value a react element
57
+ * @NOTE
58
+ * This is a same-realm compariosn only.
40
59
  */
41
- function isReactElement(value) {
42
- return !!(value && value.$$typeof);
60
+ function isPlainObject(value) {
61
+ return value.constructor === Object || value.constructor == null;
43
62
  }
44
63
  /**
45
- * in cases where WeakSet is not supported, creates a new custom
46
- * object that mimics the necessary API aspects for cache purposes
47
- *
48
- * @returns the new cache object
64
+ * When the value is `Promise`-like, aka "then-able".
49
65
  */
50
- function getNewCacheFallback() {
51
- var values = [];
52
- return {
53
- add: function (value) {
54
- values.push(value);
55
- },
56
- has: function (value) {
57
- return values.indexOf(value) !== -1;
58
- },
59
- };
66
+ function isPromiseLike(value) {
67
+ return typeof value.then === 'function';
60
68
  }
61
69
  /**
62
- * get a new cache object to prevent circular references
63
- *
64
- * @returns the new cache object
70
+ * Whether the values passed are strictly equal or both NaN.
65
71
  */
66
- var getNewCache = (function (canUseWeakMap) {
67
- if (canUseWeakMap) {
68
- return function _getNewCache() {
69
- return new WeakSet();
70
- };
72
+ function sameValueZeroEqual(a, b) {
73
+ return a === b || (a !== a && b !== b);
74
+ }
75
+
76
+ var ARGUMENTS_TAG = '[object Arguments]';
77
+ var BOOLEAN_TAG = '[object Boolean]';
78
+ var DATE_TAG = '[object Date]';
79
+ var REG_EXP_TAG = '[object RegExp]';
80
+ var MAP_TAG = '[object Map]';
81
+ var NUMBER_TAG = '[object Number]';
82
+ var OBJECT_TAG = '[object Object]';
83
+ var SET_TAG = '[object Set]';
84
+ var STRING_TAG = '[object String]';
85
+ var toString = Object.prototype.toString;
86
+ function createComparator(_a) {
87
+ var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areMapsEqual = _a.areMapsEqual, areObjectsEqual = _a.areObjectsEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual, createIsNestedEqual = _a.createIsNestedEqual;
88
+ var isEqual = createIsNestedEqual(comparator);
89
+ /**
90
+ * compare the value of the two objects and return true if they are equivalent in values
91
+ */
92
+ function comparator(a, b, meta) {
93
+ // If the items are strictly equal, no need to do a value comparison.
94
+ if (a === b) {
95
+ return true;
96
+ }
97
+ // If the items are not non-nullish objects, then the only possibility
98
+ // of them being equal but not strictly is if they are both `NaN`. Since
99
+ // `NaN` is uniquely not equal to itself, we can use self-comparison of
100
+ // both objects, which is faster than `isNaN()`.
101
+ if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
102
+ return a !== a && b !== b;
103
+ }
104
+ // Checks are listed in order of commonality of use-case:
105
+ // 1. Common complex object types (plain object, array)
106
+ // 2. Common data values (date, regexp)
107
+ // 3. Less-common complex object types (map, set)
108
+ // 4. Less-common data values (promise, primitive wrappers)
109
+ // Inherently this is both subjective and assumptive, however
110
+ // when reviewing comparable libraries in the wild this order
111
+ // appears to be generally consistent.
112
+ // `isPlainObject` only checks against the object's own realm. Cross-realm
113
+ // comparisons are rare, and will be handled in the ultimate fallback, so
114
+ // we can avoid the `toString.call()` cost unless necessary.
115
+ if (isPlainObject(a) && isPlainObject(b)) {
116
+ return areObjectsEqual(a, b, isEqual, meta);
117
+ }
118
+ // `isArray()` works on subclasses and is cross-realm, so we can again avoid
119
+ // the `toString.call()` cost unless necessary by just checking if either
120
+ // and then both are arrays.
121
+ var aArray = Array.isArray(a);
122
+ var bArray = Array.isArray(b);
123
+ if (aArray || bArray) {
124
+ return aArray === bArray && areArraysEqual(a, b, isEqual, meta);
125
+ }
126
+ // Since this is a custom object, use the classic `toString.call()` to get its
127
+ // type. This is reasonably performant in modern environments like v8 and
128
+ // SpiderMonkey, and allows for cross-realm comparison when other checks like
129
+ // `instanceof` do not.
130
+ var aTag = toString.call(a);
131
+ if (aTag !== toString.call(b)) {
132
+ return false;
133
+ }
134
+ if (aTag === DATE_TAG) {
135
+ // `getTime()` showed better results compared to alternatives like `valueOf()`
136
+ // or the unary `+` operator.
137
+ return areDatesEqual(a, b, isEqual, meta);
138
+ }
139
+ if (aTag === REG_EXP_TAG) {
140
+ return areRegExpsEqual(a, b, isEqual, meta);
141
+ }
142
+ if (aTag === MAP_TAG) {
143
+ return areMapsEqual(a, b, isEqual, meta);
144
+ }
145
+ if (aTag === SET_TAG) {
146
+ return areSetsEqual(a, b, isEqual, meta);
147
+ }
148
+ // If a simple object tag, then we can prioritize a simple object comparison because
149
+ // it is likely a custom class. If an arguments tag, it should be treated as a standard
150
+ // object.
151
+ if (aTag === OBJECT_TAG || aTag === ARGUMENTS_TAG) {
152
+ // The exception for value comparison is `Promise`-like contracts. These should be
153
+ // treated the same as standard `Promise` objects, which means strict equality.
154
+ return isPromiseLike(a) || isPromiseLike(b)
155
+ ? a === b
156
+ : areObjectsEqual(a, b, isEqual, meta);
157
+ }
158
+ // As the penultimate fallback, check if the values passed are primitive wrappers. This
159
+ // is very rare in modern JS, which is why it is deprioritized compared to all other object
160
+ // types.
161
+ if (aTag === BOOLEAN_TAG || aTag === NUMBER_TAG || aTag === STRING_TAG) {
162
+ return sameValueZeroEqual(a.valueOf(), b.valueOf());
163
+ }
164
+ // If not matching any tags that require a specific type of comparison, then use strict
165
+ // equality. This is for a few reasons:
166
+ // - For types that cannot be introspected (`Promise`, `WeakMap`, etc.), this is the only
167
+ // comparison that can be made.
168
+ // - For types that can be introspected, but rarely have requirements to be compared
169
+ // (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
170
+ // use-cases.
171
+ // - For types that can be introspected, but do not have an objective definition of what
172
+ // equality is (`Error`, etc.), the subjective decision was to be conservative.
173
+ // In all cases, these decisions should be reevaluated based on changes to the language and
174
+ // common development practices.
175
+ return a === b;
71
176
  }
72
- return getNewCacheFallback;
73
- })(HAS_WEAKSET_SUPPORT);
74
- /**
75
- * create a custom isEqual handler specific to circular objects
76
- *
77
- * @param [isEqual] the isEqual comparator to use instead of isDeepEqual
78
- * @returns the method to create the `isEqual` function
79
- */
80
- function createCircularEqualCreator(isEqual) {
81
- return function createCircularEqual(comparator) {
82
- var _comparator = isEqual || comparator;
83
- return function circularEqual(a, b, indexOrKeyA, indexOrKeyB, parentA, parentB, cache) {
84
- if (cache === void 0) { cache = getNewCache(); }
85
- var isCacheableA = !!a && typeof a === 'object';
86
- var isCacheableB = !!b && typeof b === 'object';
87
- if (isCacheableA || isCacheableB) {
88
- var hasA = isCacheableA && cache.has(a);
89
- var hasB = isCacheableB && cache.has(b);
90
- if (hasA || hasB) {
91
- return hasA && hasB;
92
- }
93
- if (isCacheableA) {
94
- cache.add(a);
95
- }
96
- if (isCacheableB) {
97
- cache.add(b);
98
- }
99
- }
100
- return _comparator(a, b, cache);
101
- };
102
- };
103
- }
177
+ return comparator;
178
+ }
179
+
104
180
  /**
105
- * are the arrays equal in value
106
- *
107
- * @param a the array to test
108
- * @param b the array to test against
109
- * @param isEqual the comparator to determine equality
110
- * @param meta the meta object to pass through
111
- * @returns are the arrays equal
181
+ * Whether the arrays are equal in value.
112
182
  */
113
183
  function areArraysEqual(a, b, isEqual, meta) {
114
184
  var index = a.length;
115
185
  if (b.length !== index) {
116
186
  return false;
117
187
  }
188
+ // Decrementing `while` showed faster results than either incrementing or
189
+ // decrementing `for` loop and than an incrementing `while` loop. Declarative
190
+ // methods like `some` / `every` were not used to avoid incurring the garbage
191
+ // cost of anonymous callbacks.
118
192
  while (index-- > 0) {
119
193
  if (!isEqual(a[index], b[index], index, index, a, b, meta)) {
120
194
  return false;
@@ -123,199 +197,228 @@ function areArraysEqual(a, b, isEqual, meta) {
123
197
  return true;
124
198
  }
125
199
  /**
126
- * are the maps equal in value
200
+ * Whether the arrays are equal in value, including circular references.
201
+ */
202
+ var areArraysEqualCircular = createIsCircular(areArraysEqual);
203
+
204
+ /**
205
+ * Whether the dates passed are equal in value.
127
206
  *
128
- * @param a the map to test
129
- * @param b the map to test against
130
- * @param isEqual the comparator to determine equality
131
- * @param meta the meta map to pass through
132
- * @returns are the maps equal
207
+ * @NOTE
208
+ * This is a standalone function instead of done inline in the comparator
209
+ * to allow for overrides.
210
+ */
211
+ function areDatesEqual(a, b) {
212
+ return sameValueZeroEqual(a.valueOf(), b.valueOf());
213
+ }
214
+
215
+ /**
216
+ * Whether the `Map`s are equal in value.
133
217
  */
134
218
  function areMapsEqual(a, b, isEqual, meta) {
135
219
  var isValueEqual = a.size === b.size;
136
- if (isValueEqual && a.size) {
137
- var matchedIndices_1 = {};
138
- var indexA_1 = 0;
139
- a.forEach(function (aValue, aKey) {
140
- if (isValueEqual) {
141
- var hasMatch_1 = false;
142
- var matchIndexB_1 = 0;
143
- b.forEach(function (bValue, bKey) {
144
- if (!hasMatch_1 && !matchedIndices_1[matchIndexB_1]) {
145
- hasMatch_1 =
146
- isEqual(aKey, bKey, indexA_1, matchIndexB_1, a, b, meta) &&
147
- isEqual(aValue, bValue, aKey, bKey, a, b, meta);
148
- if (hasMatch_1) {
149
- matchedIndices_1[matchIndexB_1] = true;
150
- }
151
- }
152
- matchIndexB_1++;
153
- });
154
- indexA_1++;
155
- isValueEqual = hasMatch_1;
220
+ if (!isValueEqual) {
221
+ return false;
222
+ }
223
+ if (!a.size) {
224
+ return true;
225
+ }
226
+ // The use of `forEach()` is to avoid the transpilation cost of `for...of` comparisons, and
227
+ // the inability to control the performance of the resulting code. It also avoids excessive
228
+ // iteration compared to doing comparisons of `keys()` and `values()`. As a result, though,
229
+ // we cannot short-circuit the iterations; bookkeeping must be done to short-circuit the
230
+ // equality checks themselves.
231
+ var matchedIndices = {};
232
+ var indexA = 0;
233
+ a.forEach(function (aValue, aKey) {
234
+ if (!isValueEqual) {
235
+ return;
236
+ }
237
+ var hasMatch = false;
238
+ var matchIndexB = 0;
239
+ b.forEach(function (bValue, bKey) {
240
+ if (!hasMatch &&
241
+ !matchedIndices[matchIndexB] &&
242
+ (hasMatch =
243
+ isEqual(aKey, bKey, indexA, matchIndexB, a, b, meta) &&
244
+ isEqual(aValue, bValue, aKey, bKey, a, b, meta))) {
245
+ matchedIndices[matchIndexB] = true;
156
246
  }
247
+ matchIndexB++;
157
248
  });
158
- }
249
+ indexA++;
250
+ isValueEqual = hasMatch;
251
+ });
159
252
  return isValueEqual;
160
253
  }
254
+ /**
255
+ * Whether the `Map`s are equal in value, including circular references.
256
+ */
257
+ var areMapsEqualCircular = createIsCircular(areMapsEqual);
258
+
161
259
  var OWNER = '_owner';
162
- var hasOwnProperty = Function.prototype.bind.call(Function.prototype.call, Object.prototype.hasOwnProperty);
260
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
163
261
  /**
164
- * are the objects equal in value
165
- *
166
- * @param a the object to test
167
- * @param b the object to test against
168
- * @param isEqual the comparator to determine equality
169
- * @param meta the meta object to pass through
170
- * @returns are the objects equal
262
+ * Whether the objects are equal in value.
171
263
  */
172
264
  function areObjectsEqual(a, b, isEqual, meta) {
173
- var keysA = keys(a);
265
+ var keysA = Object.keys(a);
174
266
  var index = keysA.length;
175
- if (keys(b).length !== index) {
267
+ if (Object.keys(b).length !== index) {
176
268
  return false;
177
269
  }
178
- if (index) {
179
- var key = void 0;
180
- while (index-- > 0) {
181
- key = keysA[index];
182
- if (key === OWNER) {
183
- var reactElementA = isReactElement(a);
184
- var reactElementB = isReactElement(b);
185
- if ((reactElementA || reactElementB) &&
186
- reactElementA !== reactElementB) {
187
- return false;
188
- }
189
- }
190
- if (!hasOwnProperty(b, key) ||
191
- !isEqual(a[key], b[key], key, key, a, b, meta)) {
270
+ var key;
271
+ // Decrementing `while` showed faster results than either incrementing or
272
+ // decrementing `for` loop and than an incrementing `while` loop. Declarative
273
+ // methods like `some` / `every` were not used to avoid incurring the garbage
274
+ // cost of anonymous callbacks.
275
+ while (index-- > 0) {
276
+ key = keysA[index];
277
+ if (key === OWNER) {
278
+ var reactElementA = !!a.$$typeof;
279
+ var reactElementB = !!b.$$typeof;
280
+ if ((reactElementA || reactElementB) && reactElementA !== reactElementB) {
192
281
  return false;
193
282
  }
194
283
  }
284
+ if (!hasOwnProperty.call(b, key) ||
285
+ !isEqual(a[key], b[key], key, key, a, b, meta)) {
286
+ return false;
287
+ }
195
288
  }
196
289
  return true;
197
290
  }
198
291
  /**
199
- * are the regExps equal in value
292
+ * Whether the objects are equal in value, including circular references.
293
+ */
294
+ var areObjectsEqualCircular = createIsCircular(areObjectsEqual);
295
+
296
+ /**
297
+ * Whether the regexps passed are equal in value.
200
298
  *
201
- * @param a the regExp to test
202
- * @param b the regExp to test agains
203
- * @returns are the regExps equal
299
+ * @NOTE
300
+ * This is a standalone function instead of done inline in the comparator
301
+ * to allow for overrides. An example of this would be supporting a
302
+ * pre-ES2015 environment where the `flags` property is not available.
204
303
  */
205
304
  function areRegExpsEqual(a, b) {
206
- return (a.source === b.source &&
207
- a.global === b.global &&
208
- a.ignoreCase === b.ignoreCase &&
209
- a.multiline === b.multiline &&
210
- a.unicode === b.unicode &&
211
- a.sticky === b.sticky &&
212
- a.lastIndex === b.lastIndex);
213
- }
305
+ return a.source === b.source && a.flags === b.flags;
306
+ }
307
+
214
308
  /**
215
- * are the sets equal in value
216
- *
217
- * @param a the set to test
218
- * @param b the set to test against
219
- * @param isEqual the comparator to determine equality
220
- * @param meta the meta set to pass through
221
- * @returns are the sets equal
309
+ * Whether the `Set`s are equal in value.
222
310
  */
223
311
  function areSetsEqual(a, b, isEqual, meta) {
224
312
  var isValueEqual = a.size === b.size;
225
- if (isValueEqual && a.size) {
226
- var matchedIndices_2 = {};
227
- a.forEach(function (aValue, aKey) {
228
- if (isValueEqual) {
229
- var hasMatch_2 = false;
230
- var matchIndex_1 = 0;
231
- b.forEach(function (bValue, bKey) {
232
- if (!hasMatch_2 && !matchedIndices_2[matchIndex_1]) {
233
- hasMatch_2 = isEqual(aValue, bValue, aKey, bKey, a, b, meta);
234
- if (hasMatch_2) {
235
- matchedIndices_2[matchIndex_1] = true;
236
- }
237
- }
238
- matchIndex_1++;
239
- });
240
- isValueEqual = hasMatch_2;
313
+ if (!isValueEqual) {
314
+ return false;
315
+ }
316
+ if (!a.size) {
317
+ return true;
318
+ }
319
+ // The use of `forEach()` is to avoid the transpilation cost of `for...of` comparisons, and
320
+ // the inability to control the performance of the resulting code. It also avoids excessive
321
+ // iteration compared to doing comparisons of `keys()` and `values()`. As a result, though,
322
+ // we cannot short-circuit the iterations; bookkeeping must be done to short-circuit the
323
+ // equality checks themselves.
324
+ var matchedIndices = {};
325
+ a.forEach(function (aValue, aKey) {
326
+ if (!isValueEqual) {
327
+ return;
328
+ }
329
+ var hasMatch = false;
330
+ var matchIndex = 0;
331
+ b.forEach(function (bValue, bKey) {
332
+ if (!hasMatch &&
333
+ !matchedIndices[matchIndex] &&
334
+ (hasMatch = isEqual(aValue, bValue, aKey, bKey, a, b, meta))) {
335
+ matchedIndices[matchIndex] = true;
241
336
  }
337
+ matchIndex++;
242
338
  });
243
- }
339
+ isValueEqual = hasMatch;
340
+ });
244
341
  return isValueEqual;
245
- }
342
+ }
343
+ /**
344
+ * Whether the `Set`s are equal in value, including circular references.
345
+ */
346
+ var areSetsEqualCircular = createIsCircular(areSetsEqual);
246
347
 
247
- var HAS_MAP_SUPPORT = typeof Map === 'function';
248
- var HAS_SET_SUPPORT = typeof Set === 'function';
249
- function createComparator(createIsEqual) {
250
- var isEqual =
251
- /* eslint-disable no-use-before-define */
252
- typeof createIsEqual === 'function'
253
- ? createIsEqual(comparator)
254
- : function (a, b, indexOrKeyA, indexOrKeyB, parentA, parentB, meta) { return comparator(a, b, meta); };
255
- /* eslint-enable */
256
- /**
257
- * compare the value of the two objects and return true if they are equivalent in values
258
- *
259
- * @param a the value to test against
260
- * @param b the value to test
261
- * @param [meta] an optional meta object that is passed through to all equality test calls
262
- * @returns are a and b equivalent in value
263
- */
264
- function comparator(a, b, meta) {
265
- if (a === b) {
266
- return true;
267
- }
268
- if (a && b && typeof a === 'object' && typeof b === 'object') {
269
- if (isPlainObject(a) && isPlainObject(b)) {
270
- return areObjectsEqual(a, b, isEqual, meta);
271
- }
272
- var aShape = Array.isArray(a);
273
- var bShape = Array.isArray(b);
274
- if (aShape || bShape) {
275
- return aShape === bShape && areArraysEqual(a, b, isEqual, meta);
276
- }
277
- aShape = a instanceof Date;
278
- bShape = b instanceof Date;
279
- if (aShape || bShape) {
280
- return (aShape === bShape && sameValueZeroEqual(a.getTime(), b.getTime()));
281
- }
282
- aShape = a instanceof RegExp;
283
- bShape = b instanceof RegExp;
284
- if (aShape || bShape) {
285
- return aShape === bShape && areRegExpsEqual(a, b);
286
- }
287
- if (isPromiseLike(a) || isPromiseLike(b)) {
288
- return a === b;
289
- }
290
- if (HAS_MAP_SUPPORT) {
291
- aShape = a instanceof Map;
292
- bShape = b instanceof Map;
293
- if (aShape || bShape) {
294
- return aShape === bShape && areMapsEqual(a, b, isEqual, meta);
295
- }
296
- }
297
- if (HAS_SET_SUPPORT) {
298
- aShape = a instanceof Set;
299
- bShape = b instanceof Set;
300
- if (aShape || bShape) {
301
- return aShape === bShape && areSetsEqual(a, b, isEqual, meta);
302
- }
303
- }
304
- return areObjectsEqual(a, b, isEqual, meta);
305
- }
306
- return a !== a && b !== b;
307
- }
308
- return comparator;
348
+ var DEFAULT_CONFIG = Object.freeze({
349
+ areArraysEqual: areArraysEqual,
350
+ areDatesEqual: areDatesEqual,
351
+ areMapsEqual: areMapsEqual,
352
+ areObjectsEqual: areObjectsEqual,
353
+ areRegExpsEqual: areRegExpsEqual,
354
+ areSetsEqual: areSetsEqual,
355
+ createIsNestedEqual: createDefaultIsNestedEqual,
356
+ });
357
+ var DEFAULT_CIRCULAR_CONFIG = Object.freeze(merge(DEFAULT_CONFIG, {
358
+ areArraysEqual: areArraysEqualCircular,
359
+ areMapsEqual: areMapsEqualCircular,
360
+ areObjectsEqual: areObjectsEqualCircular,
361
+ areSetsEqual: areSetsEqualCircular,
362
+ }));
363
+ var isDeepEqual = createComparator(DEFAULT_CONFIG);
364
+ /**
365
+ * Whether the items passed are deeply-equal in value.
366
+ */
367
+ function deepEqual(a, b) {
368
+ return isDeepEqual(a, b, undefined);
369
+ }
370
+ var isShallowEqual = createComparator(merge(DEFAULT_CONFIG, { createIsNestedEqual: function () { return sameValueZeroEqual; } }));
371
+ /**
372
+ * Whether the items passed are shallowly-equal in value.
373
+ */
374
+ function shallowEqual(a, b) {
375
+ return isShallowEqual(a, b, undefined);
376
+ }
377
+ var isCircularDeepEqual = createComparator(DEFAULT_CIRCULAR_CONFIG);
378
+ /**
379
+ * Whether the items passed are deeply-equal in value, including circular references.
380
+ */
381
+ function circularDeepEqual(a, b) {
382
+ return isCircularDeepEqual(a, b, new WeakMap());
383
+ }
384
+ var isCircularShallowEqual = createComparator(merge(DEFAULT_CIRCULAR_CONFIG, {
385
+ createIsNestedEqual: function () { return sameValueZeroEqual; },
386
+ }));
387
+ /**
388
+ * Whether the items passed are shallowly-equal in value, including circular references.
389
+ */
390
+ function circularShallowEqual(a, b) {
391
+ return isCircularShallowEqual(a, b, new WeakMap());
392
+ }
393
+ /**
394
+ * Create a custom equality comparison method.
395
+ *
396
+ * This can be done to create very targeted comparisons in extreme hot-path scenarios
397
+ * where the standard methods are not performant enough, but can also be used to provide
398
+ * support for legacy environments that do not support expected features like
399
+ * `RegExp.prototype.flags` out of the box.
400
+ */
401
+ function createCustomEqual(getComparatorOptions) {
402
+ return createComparator(merge(DEFAULT_CONFIG, getComparatorOptions(DEFAULT_CONFIG)));
403
+ }
404
+ /**
405
+ * Create a custom equality comparison method that handles circular references. This is very
406
+ * similar to `createCustomEqual`, with the only difference being that `meta` expects to be
407
+ * populated with a `WeakMap`-like contract.
408
+ *
409
+ * This can be done to create very targeted comparisons in extreme hot-path scenarios
410
+ * where the standard methods are not performant enough, but can also be used to provide
411
+ * support for legacy environments that do not support expected features like
412
+ * `WeakMap` out of the box.
413
+ */
414
+ function createCustomCircularEqual(getComparatorOptions) {
415
+ return createComparator(merge(DEFAULT_CIRCULAR_CONFIG, getComparatorOptions(DEFAULT_CIRCULAR_CONFIG)));
309
416
  }
310
417
 
311
- var deepEqual = createComparator();
312
- var shallowEqual = createComparator(function () { return sameValueZeroEqual; });
313
- var circularDeepEqual = createComparator(createCircularEqualCreator());
314
- var circularShallowEqual = createComparator(createCircularEqualCreator(sameValueZeroEqual));
315
-
316
418
  exports.circularDeepEqual = circularDeepEqual;
317
419
  exports.circularShallowEqual = circularShallowEqual;
318
- exports.createCustomEqual = createComparator;
420
+ exports.createCustomCircularEqual = createCustomCircularEqual;
421
+ exports.createCustomEqual = createCustomEqual;
319
422
  exports.deepEqual = deepEqual;
320
423
  exports.sameValueZeroEqual = sameValueZeroEqual;
321
424
  exports.shallowEqual = shallowEqual;