fast-equals 5.0.0-beta.2 → 5.0.0-beta.4

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.
package/CHANGELOG.md CHANGED
@@ -31,11 +31,15 @@ The following new comparators are available:
31
31
 
32
32
  This will perform the same comparisons as their non-strict counterparts, but will verify additional properties (non-enumerable properties on objects, keyed objects on `Array` / `Map` / `Set`) and that the descriptors for the properties align.
33
33
 
34
+ #### `TypedArray` support
35
+
36
+ Support for comparing all typed array values is now supported, and you can provide a custom comparator via the new `areTypedArraysEqual` option in the `createCustomEqual` configuration.
37
+
34
38
  #### Better build system resolution
35
39
 
36
40
  The library now leverages the `exports` property in the `package.json` to provide builds specific to your method of consumption (ESM / CommonJS / UMD). There is still a minified UMD version available if you want to use it instead.
37
41
 
38
- #### `arePrimitiveWrappersEqual` added to `createCustomEqual` configuration
42
+ #### `arePrimitiveWrappersEqual` option added to `createCustomEqual` configuration
39
43
 
40
44
  If you want a custom comparator for primitive wrappers (`new Boolean()` / `new Number()` / `new String()`) it is now available.
41
45
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/>
5
5
  <img src="https://img.shields.io/badge/license-MIT-blue.svg"/>
6
6
 
7
- Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.27kB when minified and gzipped.
7
+ Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.75kB when minified and gzipped.
8
8
 
9
9
  Unlike most equality validation libraries, the following types are handled out-of-the-box:
10
10
 
@@ -162,6 +162,7 @@ console.log(circularShallowEqual(array, [array])); // false
162
162
 
163
163
  Performs the same comparison as `deepEqual` but performs a strict comparison of the objects. In this includes:
164
164
 
165
+ - Checking constructors match
165
166
  - Checking non-enumerable properties in object comparisons
166
167
  - Checking full descriptor of properties on the object to match
167
168
  - Checking non-index properties on arrays
@@ -296,6 +297,7 @@ interface CreateComparatorCreatorOptions<Meta> {
296
297
  >;
297
298
  areRegExpsEqual: TypeEqualityComparator<RegExp, Meta>;
298
299
  areSetsEqual: TypeEqualityComparator<Set<any>, Meta>;
300
+ areTypedArraysEqual: TypeEqualityComparatory<TypedArray, Meta>;
299
301
  }
300
302
 
301
303
  interface CustomEqualCreatorOptions<Meta> {
@@ -1,112 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var ARGUMENTS_TAG = '[object Arguments]';
4
- var BOOLEAN_TAG = '[object Boolean]';
5
- var DATE_TAG = '[object Date]';
6
- var MAP_TAG = '[object Map]';
7
- var NUMBER_TAG = '[object Number]';
8
- var OBJECT_TAG = '[object Object]';
9
- var REG_EXP_TAG = '[object RegExp]';
10
- var SET_TAG = '[object Set]';
11
- var STRING_TAG = '[object String]';
12
- var isArray = Array.isArray;
13
- var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
14
- function createComparator(_a) {
15
- var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areMapsEqual = _a.areMapsEqual, areObjectsEqual = _a.areObjectsEqual, arePrimitiveWrappersEqual = _a.arePrimitiveWrappersEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual;
16
- /**
17
- * compare the value of the two objects and return true if they are equivalent in values
18
- */
19
- return function comparator(a, b, state) {
20
- // If the items are strictly equal, no need to do a value comparison.
21
- if (a === b) {
22
- return true;
23
- }
24
- // If the items are not non-nullish objects, then the only possibility
25
- // of them being equal but not strictly is if they are both `NaN`. Since
26
- // `NaN` is uniquely not equal to itself, we can use self-comparison of
27
- // both objects, which is faster than `isNaN()`.
28
- if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
29
- return a !== a && b !== b;
30
- }
31
- // Checks are listed in order of commonality of use-case:
32
- // 1. Common complex object types (plain object, array)
33
- // 2. Common data values (date, regexp)
34
- // 3. Less-common complex object types (map, set)
35
- // 4. Less-common data values (promise, primitive wrappers)
36
- // Inherently this is both subjective and assumptive, however
37
- // when reviewing comparable libraries in the wild this order
38
- // appears to be generally consistent.
39
- // `isPlainObject` only checks against the object's own realm. Cross-realm
40
- // comparisons are rare, and will be handled in the ultimate fallback, so
41
- // we can avoid the `toString.call()` cost unless necessary.
42
- if (a.constructor === Object && b.constructor === Object) {
43
- return areObjectsEqual(a, b, state);
44
- }
45
- // `isArray()` works on subclasses and is cross-realm, so we can again avoid
46
- // the `toString.call()` cost unless necessary by just checking if either
47
- // and then both are arrays.
48
- var aArray = isArray(a);
49
- var bArray = isArray(b);
50
- if (aArray || bArray) {
51
- return aArray === bArray && areArraysEqual(a, b, state);
52
- }
53
- // Since this is a custom object, use the classic `toString.call()` to get its
54
- // type. This is reasonably performant in modern environments like v8 and
55
- // SpiderMonkey, and allows for cross-realm comparison when other checks like
56
- // `instanceof` do not.
57
- var tag = getTag(a);
58
- if (tag !== getTag(b)) {
59
- return false;
60
- }
61
- if (tag === DATE_TAG) {
62
- return areDatesEqual(a, b, state);
63
- }
64
- if (tag === REG_EXP_TAG) {
65
- return areRegExpsEqual(a, b, state);
66
- }
67
- if (tag === MAP_TAG) {
68
- return areMapsEqual(a, b, state);
69
- }
70
- if (tag === SET_TAG) {
71
- return areSetsEqual(a, b, state);
72
- }
73
- // If a simple object tag, then we can prioritize a simple object comparison because
74
- // it is likely a custom class.
75
- if (tag === OBJECT_TAG) {
76
- // The exception for value comparison is `Promise`-like contracts. These should be
77
- // treated the same as standard `Promise` objects, which means strict equality, and if
78
- // it reaches this point then that strict equality comparison has already failed.
79
- return (typeof a.then !== 'function' &&
80
- typeof b.then !== 'function' &&
81
- areObjectsEqual(a, b, state));
82
- }
83
- // If an arguments tag, it should be treated as a standard object.
84
- if (tag === ARGUMENTS_TAG) {
85
- return areObjectsEqual(a, b, state);
86
- }
87
- // As the penultimate fallback, check if the values passed are primitive wrappers. This
88
- // is very rare in modern JS, which is why it is deprioritized compared to all other object
89
- // types.
90
- if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
91
- return arePrimitiveWrappersEqual(a, b, state);
92
- }
93
- // If not matching any tags that require a specific type of comparison, then we hard-code false because
94
- // the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
95
- // - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
96
- // comparison that can be made.
97
- // - For types that can be introspected, but rarely have requirements to be compared
98
- // (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
99
- // use-cases (may be included in a future release, if requested enough).
100
- // - For types that can be introspected but do not have an objective definition of what
101
- // equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
102
- // In all cases, these decisions should be reevaluated based on changes to the language and
103
- // common development practices.
104
- return false;
105
- };
106
- }
107
-
108
3
  var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
109
4
  var hasOwnProperty = Object.prototype.hasOwnProperty;
5
+ var SUPPORTS_ARRAY_BUFFER = typeof ArrayBuffer === 'function' && Boolean(ArrayBuffer.isView);
6
+ /**
7
+ * Combine two comparators into a single comparators.
8
+ */
110
9
  function combineComparators(comparatorA, comparatorB) {
111
10
  return function isEqual(a, b, state) {
112
11
  return comparatorA(a, b, state) && comparatorB(a, b, state);
@@ -145,13 +44,23 @@ function createIsCircular(areItemsEqual) {
145
44
  return result;
146
45
  };
147
46
  }
47
+ /**
48
+ * Get the properties to strictly examine, which include both own properties that are
49
+ * not enumerable and symbol properties.
50
+ */
148
51
  function getStrictProperties(object) {
149
52
  return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
150
53
  }
54
+ /**
55
+ * Whether the object contains the property passed as an own property.
56
+ */
151
57
  var hasOwn = Object.hasOwn ||
152
58
  (function (object, property) {
153
59
  return hasOwnProperty.call(object, property);
154
60
  });
61
+ function isArrayBuffer(value) {
62
+ return SUPPORTS_ARRAY_BUFFER && ArrayBuffer.isView(value);
63
+ }
155
64
  /**
156
65
  * Whether the values passed are strictly equal or both NaN.
157
66
  */
@@ -178,10 +87,6 @@ function areArraysEqual(a, b, state) {
178
87
  }
179
88
  /**
180
89
  * Whether the dates passed are equal in value.
181
- *
182
- * @NOTE
183
- * This is a standalone function instead of done inline in the comparator
184
- * to allow for overrides.
185
90
  */
186
91
  function areDatesEqual(a, b) {
187
92
  return sameValueZeroEqual(a.getTime(), b.getTime());
@@ -293,21 +198,12 @@ function areObjectsEqualStrict(a, b, state) {
293
198
  }
294
199
  /**
295
200
  * Whether the primitive wrappers passed are equal in value.
296
- *
297
- * @NOTE
298
- * This is a standalone function instead of done inline in the comparator
299
- * to allow for overrides.
300
201
  */
301
202
  function arePrimitiveWrappersEqual(a, b) {
302
203
  return sameValueZeroEqual(a.valueOf(), b.valueOf());
303
204
  }
304
205
  /**
305
206
  * Whether the regexps passed are equal in value.
306
- *
307
- * @NOTE
308
- * This is a standalone function instead of done inline in the comparator
309
- * to allow for overrides. An example of this would be supporting a
310
- * pre-ES2015 environment where the `flags` property is not available.
311
207
  */
312
208
  function areRegExpsEqual(a, b) {
313
209
  return a.source === b.source && a.flags === b.flags;
@@ -343,95 +239,218 @@ function areSetsEqual(a, b, state) {
343
239
  }
344
240
  return isValueEqual;
345
241
  }
242
+ function areTypedArraysEqual(a, b) {
243
+ var index = a.length;
244
+ if (b.length !== index) {
245
+ return false;
246
+ }
247
+ while (index-- > 0) {
248
+ if (a[index] !== b[index]) {
249
+ return false;
250
+ }
251
+ }
252
+ return true;
253
+ }
346
254
 
255
+ var ARGUMENTS_TAG = '[object Arguments]';
256
+ var BOOLEAN_TAG = '[object Boolean]';
257
+ var DATE_TAG = '[object Date]';
258
+ var MAP_TAG = '[object Map]';
259
+ var NUMBER_TAG = '[object Number]';
260
+ var OBJECT_TAG = '[object Object]';
261
+ var REG_EXP_TAG = '[object RegExp]';
262
+ var SET_TAG = '[object Set]';
263
+ var STRING_TAG = '[object String]';
264
+ var isArray = Array.isArray;
265
+ var assign = Object.assign;
266
+ var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
267
+ /**
268
+ * Create a comparator method based on the type-specific equality comparators passed.
269
+ */
270
+ function createComparator(_a) {
271
+ var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areMapsEqual = _a.areMapsEqual, areObjectsEqual = _a.areObjectsEqual, arePrimitiveWrappersEqual = _a.arePrimitiveWrappersEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual, areTypedArraysEqual = _a.areTypedArraysEqual;
272
+ /**
273
+ * compare the value of the two objects and return true if they are equivalent in values
274
+ */
275
+ return function comparator(a, b, state) {
276
+ // If the items are strictly equal, no need to do a value comparison.
277
+ if (a === b) {
278
+ return true;
279
+ }
280
+ // If the items are not non-nullish objects, then the only possibility
281
+ // of them being equal but not strictly is if they are both `NaN`. Since
282
+ // `NaN` is uniquely not equal to itself, we can use self-comparison of
283
+ // both objects, which is faster than `isNaN()`.
284
+ if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
285
+ return a !== a && b !== b;
286
+ }
287
+ // Checks are listed in order of commonality of use-case:
288
+ // 1. Common complex object types (plain object, array)
289
+ // 2. Common data values (date, regexp)
290
+ // 3. Less-common complex object types (map, set)
291
+ // 4. Less-common data values (promise, primitive wrappers)
292
+ // Inherently this is both subjective and assumptive, however
293
+ // when reviewing comparable libraries in the wild this order
294
+ // appears to be generally consistent.
295
+ // `isPlainObject` only checks against the object's own realm. Cross-realm
296
+ // comparisons are rare, and will be handled in the ultimate fallback, so
297
+ // we can avoid the `toString.call()` cost unless necessary.
298
+ if (a.constructor === Object && b.constructor === Object) {
299
+ return areObjectsEqual(a, b, state);
300
+ }
301
+ // In strict mode, constructors should match. We placed this after the plain object check
302
+ // because the constructors must match to meet plain object requirements (must both be `Object`
303
+ // in the given Realm), so it slightly improves performance on a very common use-case.
304
+ if (state.strict && a.constructor !== b.constructor) {
305
+ return false;
306
+ }
307
+ // `isArray()` works on subclasses and is cross-realm, so we can again avoid
308
+ // the `toString.call()` cost unless necessary by just checking if either
309
+ // and then both are arrays.
310
+ var aArray = isArray(a);
311
+ var bArray = isArray(b);
312
+ if (aArray || bArray) {
313
+ return aArray === bArray && areArraysEqual(a, b, state);
314
+ }
315
+ aArray = isArrayBuffer(a);
316
+ bArray = isArrayBuffer(b);
317
+ if (aArray || bArray) {
318
+ return aArray === bArray && areTypedArraysEqual(a, b, state);
319
+ }
320
+ // Since this is a custom object, use the classic `toString.call()` to get its
321
+ // type. This is reasonably performant in modern environments like v8 and
322
+ // SpiderMonkey, and allows for cross-realm comparison when other checks like
323
+ // `instanceof` do not.
324
+ var tag = getTag(a);
325
+ if (tag !== getTag(b)) {
326
+ return false;
327
+ }
328
+ if (tag === DATE_TAG) {
329
+ return areDatesEqual(a, b, state);
330
+ }
331
+ if (tag === REG_EXP_TAG) {
332
+ return areRegExpsEqual(a, b, state);
333
+ }
334
+ if (tag === MAP_TAG) {
335
+ return areMapsEqual(a, b, state);
336
+ }
337
+ if (tag === SET_TAG) {
338
+ return areSetsEqual(a, b, state);
339
+ }
340
+ // If a simple object tag, then we can prioritize a simple object comparison because
341
+ // it is likely a custom class.
342
+ if (tag === OBJECT_TAG) {
343
+ // The exception for value comparison is `Promise`-like contracts. These should be
344
+ // treated the same as standard `Promise` objects, which means strict equality, and if
345
+ // it reaches this point then that strict equality comparison has already failed.
346
+ return (typeof a.then !== 'function' &&
347
+ typeof b.then !== 'function' &&
348
+ areObjectsEqual(a, b, state));
349
+ }
350
+ // If an arguments tag, it should be treated as a standard object.
351
+ if (tag === ARGUMENTS_TAG) {
352
+ return areObjectsEqual(a, b, state);
353
+ }
354
+ // As the penultimate fallback, check if the values passed are primitive wrappers. This
355
+ // is very rare in modern JS, which is why it is deprioritized compared to all other object
356
+ // types.
357
+ if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
358
+ return arePrimitiveWrappersEqual(a, b, state);
359
+ }
360
+ // If not matching any tags that require a specific type of comparison, then we hard-code false because
361
+ // the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
362
+ // - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
363
+ // comparison that can be made.
364
+ // - For types that can be introspected, but rarely have requirements to be compared
365
+ // (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
366
+ // use-cases (may be included in a future release, if requested enough).
367
+ // - For types that can be introspected but do not have an objective definition of what
368
+ // equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
369
+ // In all cases, these decisions should be reevaluated based on changes to the language and
370
+ // common development practices.
371
+ return false;
372
+ };
373
+ }
374
+ /**
375
+ * Create the configuration object used for building comparators.
376
+ */
347
377
  function createComparatorConfig(_a) {
348
- var circular = _a.circular, strict = _a.strict;
378
+ var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
349
379
  var config = {
350
- areArraysEqual: areArraysEqual,
380
+ areArraysEqual: strict
381
+ ? areObjectsEqualStrict
382
+ : areArraysEqual,
351
383
  areDatesEqual: areDatesEqual,
352
- areMapsEqual: areMapsEqual,
353
- areObjectsEqual: areObjectsEqual,
384
+ areMapsEqual: strict
385
+ ? combineComparators(areMapsEqual, areObjectsEqualStrict)
386
+ : areMapsEqual,
387
+ areObjectsEqual: strict
388
+ ? areObjectsEqualStrict
389
+ : areObjectsEqual,
354
390
  arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
355
391
  areRegExpsEqual: areRegExpsEqual,
356
- areSetsEqual: areSetsEqual,
392
+ areSetsEqual: strict
393
+ ? combineComparators(areSetsEqual, areObjectsEqualStrict)
394
+ : areSetsEqual,
395
+ areTypedArraysEqual: strict
396
+ ? combineComparators(areTypedArraysEqual, areObjectsEqualStrict)
397
+ : areTypedArraysEqual,
357
398
  };
358
- if (strict) {
359
- config.areArraysEqual = areObjectsEqual;
360
- config.areMapsEqual = combineComparators(areMapsEqual, areObjectsEqual);
361
- config.areObjectsEqual = areObjectsEqualStrict;
362
- config.areSetsEqual = combineComparators(areSetsEqual, areObjectsEqual);
399
+ if (createCustomConfig) {
400
+ config = assign({}, config, createCustomConfig(config));
363
401
  }
364
402
  if (circular) {
365
- config.areArraysEqual = createIsCircular(config.areArraysEqual);
366
- config.areMapsEqual = createIsCircular(config.areMapsEqual);
367
- config.areObjectsEqual = createIsCircular(config.areObjectsEqual);
368
- config.areSetsEqual = createIsCircular(config.areSetsEqual);
403
+ var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
404
+ var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
405
+ var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
406
+ var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
407
+ config = assign({}, config, {
408
+ areArraysEqual: areArraysEqual$1,
409
+ areMapsEqual: areMapsEqual$1,
410
+ areObjectsEqual: areObjectsEqual$1,
411
+ areSetsEqual: areSetsEqual$1,
412
+ });
369
413
  }
370
414
  return config;
371
415
  }
372
- function createDefaultEqualCreator(options) {
373
- if (options === void 0) { options = {}; }
374
- var config = createComparatorConfig(options);
375
- var isEqual = createComparator(config);
376
- var isEqualComparator = options.comparator || createInternalComparator(isEqual);
377
- var strict = !!options.strict;
378
- if (options.circular) {
379
- return function equals(a, b) {
380
- return isEqual(a, b, {
381
- cache: new WeakMap(),
382
- equals: isEqualComparator,
383
- meta: undefined,
384
- strict: strict,
385
- });
386
- };
387
- }
388
- var state = Object.freeze({
389
- cache: undefined,
390
- equals: isEqualComparator,
391
- meta: undefined,
392
- strict: strict,
393
- });
394
- return function equals(a, b) {
395
- return isEqual(a, b, state);
396
- };
397
- }
416
+
398
417
  /**
399
418
  * Whether the items passed are deeply-equal in value.
400
419
  */
401
- var deepEqual = createDefaultEqualCreator();
420
+ var deepEqual = createCustomEqual();
402
421
  /**
403
422
  * Whether the items passed are deeply-equal in value based on strict comparison.
404
423
  */
405
- var strictDeepEqual = createDefaultEqualCreator({ strict: true });
424
+ var strictDeepEqual = createCustomEqual({ strict: true });
406
425
  /**
407
426
  * Whether the items passed are deeply-equal in value, including circular references.
408
427
  */
409
- var circularDeepEqual = createDefaultEqualCreator({ circular: true });
428
+ var circularDeepEqual = createCustomEqual({ circular: true });
410
429
  /**
411
430
  * Whether the items passed are deeply-equal in value, including circular references,
412
431
  * based on strict comparison.
413
432
  */
414
- var strictCircularDeepEqual = createDefaultEqualCreator({
433
+ var strictCircularDeepEqual = createCustomEqual({
415
434
  circular: true,
416
435
  strict: true,
417
436
  });
418
437
  /**
419
438
  * Whether the items passed are shallowly-equal in value.
420
439
  */
421
- var shallowEqual = createDefaultEqualCreator({
440
+ var shallowEqual = createCustomEqual({
422
441
  comparator: sameValueZeroEqual,
423
442
  });
424
443
  /**
425
444
  * Whether the items passed are shallowly-equal in value based on strict comparison
426
445
  */
427
- var strictShallowEqual = createDefaultEqualCreator({
446
+ var strictShallowEqual = createCustomEqual({
428
447
  comparator: sameValueZeroEqual,
429
448
  strict: true,
430
449
  });
431
450
  /**
432
451
  * Whether the items passed are shallowly-equal in value, including circular references.
433
452
  */
434
- var circularShallowEqual = createDefaultEqualCreator({
453
+ var circularShallowEqual = createCustomEqual({
435
454
  comparator: sameValueZeroEqual,
436
455
  circular: true,
437
456
  });
@@ -439,7 +458,7 @@ var circularShallowEqual = createDefaultEqualCreator({
439
458
  * Whether the items passed are shallowly-equal in value, including circular references,
440
459
  * based on strict comparison.
441
460
  */
442
- var strictCircularShallowEqual = createDefaultEqualCreator({
461
+ var strictCircularShallowEqual = createCustomEqual({
443
462
  comparator: sameValueZeroEqual,
444
463
  circular: true,
445
464
  strict: true,
@@ -454,35 +473,31 @@ var strictCircularShallowEqual = createDefaultEqualCreator({
454
473
  */
455
474
  function createCustomEqual(options) {
456
475
  if (options === void 0) { options = {}; }
457
- var comparator = options.comparator, createCustomInternalComparator = options.createInternalComparator, createCustomConfig = options.createCustomConfig, createState = options.createState;
458
- var baseConfig = createComparatorConfig(options);
459
- var config = createCustomConfig
460
- ? Object.assign({}, baseConfig, createCustomConfig(baseConfig))
461
- : baseConfig;
462
- var isEqualCustom = comparator || createComparator(config);
463
- var isEqualCustomComparator = createCustomInternalComparator
464
- ? createCustomInternalComparator(isEqualCustom)
465
- : createInternalComparator(isEqualCustom);
466
- var strict = !!options.strict;
476
+ var circular = options.circular, comparator = options.comparator, createCustomInternalComparator = options.createInternalComparator, createState = options.createState, _a = options.strict, baseStrict = _a === void 0 ? false : _a;
477
+ var config = createComparatorConfig(options);
478
+ var isEqualCustom = createComparator(config);
479
+ var isEqualCustomComparator = comparator ||
480
+ (createCustomInternalComparator
481
+ ? createCustomInternalComparator(isEqualCustom)
482
+ : createInternalComparator(isEqualCustom));
467
483
  if (createState) {
468
484
  return function isEqual(a, b, metaOverride) {
469
- var customState = createState(isEqualCustom);
485
+ var _a = createState(isEqualCustom), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, _c = _a.equals, equals = _c === void 0 ? isEqualCustomComparator : _c, meta = _a.meta, _d = _a.strict, strict = _d === void 0 ? baseStrict : _d;
470
486
  return isEqualCustom(a, b, {
471
- cache: customState.cache || new WeakMap(),
472
- equals: customState.equals || isEqualCustomComparator,
473
- // @ts-expect-error - inferred `Meta` may be undefined, which is okay
474
- meta: metaOverride !== undefined ? metaOverride : customState.meta,
475
- strict: customState.strict !== undefined ? customState.strict : strict,
487
+ cache: cache,
488
+ equals: equals,
489
+ meta: metaOverride !== undefined ? metaOverride : meta,
490
+ strict: strict,
476
491
  });
477
492
  };
478
493
  }
479
- if (options.circular) {
494
+ if (circular) {
480
495
  return function equals(a, b) {
481
496
  return isEqualCustom(a, b, {
482
497
  cache: new WeakMap(),
483
498
  equals: isEqualCustomComparator,
484
499
  meta: undefined,
485
- strict: strict,
500
+ strict: baseStrict,
486
501
  });
487
502
  };
488
503
  }
@@ -490,7 +505,7 @@ function createCustomEqual(options) {
490
505
  cache: undefined,
491
506
  equals: isEqualCustomComparator,
492
507
  meta: undefined,
493
- strict: strict,
508
+ strict: baseStrict,
494
509
  });
495
510
  return function equals(a, b) {
496
511
  return isEqualCustom(a, b, state);