fast-equals 6.0.0-rc.1 → 6.0.1

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/README.md CHANGED
@@ -1,12 +1,7 @@
1
- # fast-equals
1
+ > fast-equals
2
2
 
3
- <img src="https://img.shields.io/badge/build-passing-brightgreen.svg"/>
4
- <img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/>
5
- <img src="https://img.shields.io/badge/license-MIT-blue.svg"/>
6
-
7
- Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed, while also
8
- maintaining a high degree of flexibility for various implementation use-cases. It has no dependencies, and is ~2kB when
9
- minified and gzipped.
3
+ Perform [blazing fast](#benchmarks) equality comparisons between two objects, while also allowing for flexibility for
4
+ various use-cases. It has no dependencies, and is ~2kB when minified and gzipped.
10
5
 
11
6
  The following types are handled out-of-the-box:
12
7
 
@@ -16,36 +11,43 @@ The following types are handled out-of-the-box:
16
11
  - `Date` objects
17
12
  - `RegExp` objects
18
13
  - `Map` / `Set` iterables
19
- - `Promise` objects
14
+ - `Promise` objects and then-ables
20
15
  - Primitive wrappers (`new Boolean()` / `new Number()` / `new String()`)
21
16
  - Custom class instances, including subclasses of native classes
22
17
 
23
- Methods are available for deep, shallow, or referential equality comparison. In addition, you can opt into support for
24
- circular objects, or performing a "strict" comparison with unconventional property definition, or both. You can also
25
- customize any specific type comparison based on your application's use-cases.
26
-
27
- ## Table of contents
28
-
29
- - [fast-equals](#fast-equals)
30
- - [Table of contents](#table-of-contents)
31
- - [Usage](#usage)
32
- - [Specific builds](#specific-builds)
33
- - [Available methods](#available-methods)
34
- - [deepEqual](#deepequal)
35
- - [Comparing `Map`s](#comparing-maps)
36
- - [shallowEqual](#shallowequal)
37
- - [sameValueEqual](#samevalueequal)
38
- - [circularDeepEqual](#circulardeepequal)
39
- - [circularShallowEqual](#circularshallowequal)
40
- - [strictDeepEqual](#strictdeepequal)
41
- - [strictShallowEqual](#strictshallowequal)
42
- - [strictCircularDeepEqual](#strictcirculardeepequal)
43
- - [strictCircularShallowEqual](#strictcircularshallowequal)
44
- - [createCustomEqual](#createcustomequal)
45
- - [getUnsupportedCustomComparator](#getunsupportedcustomcomparator)
46
- - [Recipes](#recipes)
47
- - [Benchmarks](#benchmarks)
48
- - [Development](#development)
18
+ Methods are available for deep, shallow, [`SameValue`](http://ecma-international.org/ecma-262/7.0/#sec-samevalue),
19
+ [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero), or
20
+ [strict equality](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) comparison. In addition, you
21
+ can opt into support for circular objects, or performing a "strict" comparison with unconventional property definition,
22
+ or both. You can also customize any specific type comparison based on your application's use-cases.
23
+
24
+ By default, npm should resolve the correct build of the package based on your consumption (ESM vs CommonJS). However, if
25
+ you want to force use of a specific build, they can be located here:
26
+
27
+ - ESM => `fast-equals/dist/es/index.mjs`
28
+ - CommonJS => `fast-equals/dist/cjs/index.cjs`
29
+
30
+ If you are having any problems, want to request a new feature, or have any questions,
31
+ [please file an issue](https://github.com/planttheidea/fast-equals/issues).
32
+
33
+ - [Usage](#usage)
34
+ - [Available methods](#available-methods)
35
+ - [deepEqual](#deepequal)
36
+ - [Comparing `Map`s](#comparing-maps)
37
+ - [shallowEqual](#shallowequal)
38
+ - [sameValueEqual](#samevalueequal)
39
+ - [sameValueZeroEqual](#samevaluezeroequal)
40
+ - [strictEqual](#strictequal)
41
+ - [circularDeepEqual](#circulardeepequal)
42
+ - [circularShallowEqual](#circularshallowequal)
43
+ - [strictDeepEqual](#strictdeepequal)
44
+ - [strictShallowEqual](#strictshallowequal)
45
+ - [strictCircularDeepEqual](#strictcirculardeepequal)
46
+ - [strictCircularShallowEqual](#strictcircularshallowequal)
47
+ - [createCustomEqual](#createcustomequal)
48
+ - [getUnsupportedCustomComparator](#getunsupportedcustomcomparator)
49
+ - [Recipes](#recipes)
50
+ - [Benchmarks](#benchmarks)
49
51
 
50
52
  ## Usage
51
53
 
@@ -55,19 +57,6 @@ import { deepEqual } from 'fast-equals';
55
57
  console.log(deepEqual({ foo: 'bar' }, { foo: 'bar' })); // true
56
58
  ```
57
59
 
58
- ### Specific builds
59
-
60
- By default, npm should resolve the correct build of the package based on your consumption (ESM vs CommonJS). However, if
61
- you want to force use of a specific build, they can be located here:
62
-
63
- - ESM => `fast-equals/dist/esm/index.mjs`
64
- - CommonJS => `fast-equals/dist/cjs/index.cjs`
65
- - UMD => `fast-equals/dist/umd/index.js`
66
- - Minified UMD => `fast-equals/dist/min/index.js`
67
-
68
- If you are having issues loading a specific build type,
69
- [please file an issue](https://github.com/planttheidea/fast-equals/issues).
70
-
71
60
  ## Available methods
72
61
 
73
62
  ### deepEqual
@@ -99,7 +88,7 @@ deepEqual(mapA, mapB);
99
88
  ```
100
89
 
101
90
  To support true deep equality of all contents, `fast-equals` will perform a deep equality comparison for key and value
102
- parirs. Therefore, the above would be `true`.
91
+ pairs. Therefore, the above would be `true`.
103
92
 
104
93
  ### shallowEqual
105
94
 
@@ -143,9 +132,9 @@ console.log(sameValueEqual(mainObject.foo, objectB)); // true
143
132
  console.log(sameValueEqual(mainObject, objectC)); // false
144
133
  ```
145
134
 
146
- **NOTE**: In environments that support
135
+ _**NOTE**: In environments that support
147
136
  [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is),
148
- `sameValueEqual` is just a re-export of that method.
137
+ `sameValueEqual` is just a re-export of that method._
149
138
 
150
139
  ### sameValueZeroEqual
151
140
 
@@ -170,6 +159,33 @@ console.log(sameValueEqual(mainObject.foo, objectB)); // true
170
159
  console.log(sameValueEqual(mainObject, objectC)); // false
171
160
  ```
172
161
 
162
+ ### strictEqual
163
+
164
+ Performs a [Strict Equality](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) comparison on the
165
+ two objects passed and returns a boolean representing the referential equality of the objects. In simple terms, this
166
+ means:
167
+
168
+ - `+0` and `-0` are equal
169
+ - `NaN` is not equal to `NaN`
170
+ - All other items are based on referential equality (`a === b`)
171
+
172
+ ```ts
173
+ import { strictEqual } from 'fast-equals';
174
+
175
+ const mainObject = { foo: NaN, bar: 'baz' };
176
+
177
+ const objectA = 'baz';
178
+ const objectB = NaN;
179
+ const objectC = { foo: NaN, bar: 'baz' };
180
+
181
+ console.log(sameValueEqual(mainObject.bar, objectA)); // true
182
+ console.log(sameValueEqual(mainObject.foo, objectB)); // false
183
+ console.log(sameValueEqual(mainObject, objectC)); // false
184
+ ```
185
+
186
+ _**NOTE**: This is mainly a convenience function, such as needing a default functional equality comparator. Naturally,
187
+ it is faster to simply compare `a === b`. :)_
188
+
173
189
  ### circularDeepEqual
174
190
 
175
191
  Performs the same comparison as `deepEqual` but supports circular objects. It is slower than `deepEqual`, so only use if
@@ -328,21 +344,21 @@ interface Cache<Key extends object, Value> {
328
344
  }
329
345
 
330
346
  interface ComparatorConfig<Meta> {
331
- areArrayBuffersEcqual: TypeEqualityComparator<ArrayBuffer, Meta>;
332
- areArraysEcqual: TypeEqualityComparator<any[], Meta>;
333
- areDataViewsEqual: TypeEqualityComparator<DataView, Meta>;
334
- areDatesEqual: TypeEqualityComparator<Date, Meta>;
335
- areErrorsEqual: TypeEqualityComparator<Error, Meta>;
336
- areFunctionsEqual: TypeEqualityComparator<(...args: any[]) => any, Meta>;
337
- areMapsEqual: TypeEqualityComparator<Map<any, any>, Meta>;
338
- areNumbersEqual: TypeEqualityComparator<number, Meta>;
339
- areObjectsEqual: TypeEqualityComparator<Record<string, any>, Meta>;
340
- arePrimitiveWrappersEqual: TypeEqualityComparator<Boolean | Number | String, Meta>;
341
- areRegExpsEqual: TypeEqualityComparator<RegExp, Meta>;
342
- areSetsEqual: TypeEqualityComparator<Set<any>, Meta>;
343
- areTypedArraysEqual: TypeEqualityComparator<TypedArray, Meta>;
344
- areUrlsEqual: TypeEqualityComparator<URL, Meta>;
345
- getUnsupportedCustomComparator: <Type>(a: Type, b: Type, tag: string) => TypeEqualityComparator<Type, Meta>;
347
+ areArrayBuffersEqual: EqualityComparator<Meta>;
348
+ areArraysEqual: EqualityComparator<Meta>;
349
+ areDataViewsEqual: EqualityComparator<Meta>;
350
+ areDatesEqual: EqualityComparator<Meta>;
351
+ areErrorsEqual: EqualityComparator<Meta>;
352
+ areFunctionsEqual: EqualityComparator<Meta>;
353
+ areMapsEqual: EqualityComparator<Meta>;
354
+ areNumbersEqual: EqualityComparator<Meta>;
355
+ areObjectsEqual: EqualityComparator<Meta>;
356
+ arePrimitiveWrappersEqual: EqualityComparator<Meta>;
357
+ areRegExpsEqual: EqualityComparator<Meta>;
358
+ areSetsEqual: EqualityComparator<Meta>;
359
+ areTypedArraysEqual: EqualityComparator<Meta>;
360
+ areUrlsEqual: EqualityComparator<Meta>;
361
+ getUnsupportedCustomComparator: <Type>(a: Type, b: Type, state: State<Meta>, tag: string) => EqualityComparator<Meta>;
346
362
  }
347
363
 
348
364
  function createCustomEqual<Meta>(options: {
@@ -381,7 +397,7 @@ to the problem you are solving, they can offer guidance of how to structure your
381
397
  - [Using `meta` in comparison](./recipes//using-meta-in-comparison.md)
382
398
  - [Comparing non-standard properties](./recipes/non-standard-properties.md)
383
399
  - [Strict property descriptor comparison](./recipes/strict-property-descriptor-check.md)
384
- - [Legacy environment support for circualr equal comparators](./recipes/legacy-circular-equal-support.md)
400
+ - [Legacy environment support for circular equal comparators](./recipes/legacy-circular-equal-support.md)
385
401
  - [Custom comparator support](./recipes/special-objects.md)
386
402
 
387
403
  ## Benchmarks
@@ -491,20 +507,3 @@ All of these have the potential of inflating the respective library's numbers in
491
507
  the closest apples-to-apples comparison I could create of a reasonable sample size. It should be noted that `react`
492
508
  elements can be circular objects, however simple elements are not; I kept the `react` comparison very basic to allow it
493
509
  to be included.
494
-
495
- ## Development
496
-
497
- Standard practice, clone the repo and `npm i` to get the dependencies. The following npm scripts are available:
498
-
499
- - benchmark => run benchmark tests against other equality libraries
500
- - build => build `main`, `module`, and `browser` distributables with `rollup`
501
- - clean => run `rimraf` on the `dist` folder
502
- - dev => start `vite` playground App
503
- - dist => run `build`
504
- - lint => run ESLint on all files in `src` folder (also runs on `dev` script)
505
- - lint:fix => run `lint` script, but with auto-fixer
506
- - prepublish:compile => run `lint`, `test:coverage`, `transpile:lib`, `transpile:es`, and `dist` scripts
507
- - start => run `dev`
508
- - test => run AVA with NODE_ENV=test on all files in `test` folder
509
- - test:coverage => run same script as `test` with code coverage calculation via `nyc`
510
- - test:watch => run same script as `test` but keep persistent watcher
@@ -40,7 +40,10 @@ function createIsCircular(areItemsEqual) {
40
40
  * not enumerable and symbol properties.
41
41
  */
42
42
  function getStrictProperties(object) {
43
- return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
43
+ const symbols = getOwnPropertySymbols(object);
44
+ return symbols.length
45
+ ? getOwnPropertyNames(object).concat(symbols)
46
+ : getOwnPropertyNames(object);
44
47
  }
45
48
  /**
46
49
  * Whether the object contains the property passed as an own property.
@@ -75,6 +78,18 @@ Object.is
75
78
  function sameValueZeroEqual(a, b) {
76
79
  return a === b || (a !== a && b !== b);
77
80
  }
81
+ /**
82
+ * Whether the values passed are equal based on a
83
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
84
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
85
+ *
86
+ * @note
87
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
88
+ * two objects is used.
89
+ */
90
+ function strictEqual(a, b) {
91
+ return a === b;
92
+ }
78
93
  /**
79
94
  * Whether the array buffers are equal in value.
80
95
  */
@@ -115,12 +130,6 @@ function areDatesEqual(a, b) {
115
130
  function areErrorsEqual(a, b) {
116
131
  return a.name === b.name && a.message === b.message && a.cause === b.cause && a.stack === b.stack;
117
132
  }
118
- /**
119
- * Whether the functions passed are equal in value.
120
- */
121
- function areFunctionsEqual(a, b) {
122
- return a === b;
123
- }
124
133
  /**
125
134
  * Whether the `Map`s are equal in value.
126
135
  */
@@ -132,7 +141,7 @@ function areMapsEqual(a, b, state) {
132
141
  if (!size) {
133
142
  return true;
134
143
  }
135
- const matchedIndices = new Array(size);
144
+ const matchedIndices = new Uint8Array(size);
136
145
  const aIterable = a.entries();
137
146
  let aResult;
138
147
  let bResult;
@@ -143,7 +152,7 @@ function areMapsEqual(a, b, state) {
143
152
  break;
144
153
  }
145
154
  const bIterable = b.entries();
146
- let hasMatch = false;
155
+ let hasMatch = 0;
147
156
  let matchIndex = 0;
148
157
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
149
158
  while ((bResult = bIterable.next())) {
@@ -158,7 +167,7 @@ function areMapsEqual(a, b, state) {
158
167
  const bEntry = bResult.value;
159
168
  if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state)
160
169
  && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
161
- hasMatch = matchedIndices[matchIndex] = true;
170
+ hasMatch = matchedIndices[matchIndex] = 1;
162
171
  break;
163
172
  }
164
173
  matchIndex++;
@@ -170,10 +179,6 @@ function areMapsEqual(a, b, state) {
170
179
  }
171
180
  return true;
172
181
  }
173
- /**
174
- * Whether the numbers are equal in value.
175
- */
176
- const areNumbersEqual = sameValueEqual;
177
182
  /**
178
183
  * Whether the objects are equal in value.
179
184
  */
@@ -251,7 +256,7 @@ function areSetsEqual(a, b, state) {
251
256
  if (!size) {
252
257
  return true;
253
258
  }
254
- const matchedIndices = new Array(size);
259
+ const matchedIndices = new Uint8Array(size);
255
260
  const aIterable = a.values();
256
261
  let aResult;
257
262
  let bResult;
@@ -261,7 +266,7 @@ function areSetsEqual(a, b, state) {
261
266
  break;
262
267
  }
263
268
  const bIterable = b.values();
264
- let hasMatch = false;
269
+ let hasMatch = 0;
265
270
  let matchIndex = 0;
266
271
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
267
272
  while ((bResult = bIterable.next())) {
@@ -270,7 +275,7 @@ function areSetsEqual(a, b, state) {
270
275
  }
271
276
  if (!matchedIndices[matchIndex]
272
277
  && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
273
- hasMatch = matchedIndices[matchIndex] = true;
278
+ hasMatch = matchedIndices[matchIndex] = 1;
274
279
  break;
275
280
  }
276
281
  matchIndex++;
@@ -285,8 +290,8 @@ function areSetsEqual(a, b, state) {
285
290
  * Whether the TypedArray instances are equal in value.
286
291
  */
287
292
  function areTypedArraysEqual(a, b) {
288
- let index = a.byteLength;
289
- if (b.byteLength !== index || a.byteOffset !== b.byteOffset) {
293
+ let index = a.length;
294
+ if (b.length !== index || a.byteOffset !== b.byteOffset) {
290
295
  return false;
291
296
  }
292
297
  while (index-- > 0) {
@@ -368,8 +373,8 @@ function createEqualityComparator(config) {
368
373
  // Try to fast-path equality checks for other complex object types in the
369
374
  // same realm to avoid capturing the string tag. Strict equality is used
370
375
  // instead of `instanceof` because it is more performant for the common
371
- // use-case. If someone is subclassing a native class, it will be handled
372
- // with the string tag comparison.
376
+ // use-case. If someone is creating a subclass from a native class, it will be
377
+ // handled with the string tag comparison.
373
378
  if (constructor === Object) {
374
379
  return areObjectsEqual(a, b, state);
375
380
  }
@@ -398,14 +403,14 @@ function createEqualityComparator(config) {
398
403
  if (Array.isArray(a)) {
399
404
  return areArraysEqual(a, b, state);
400
405
  }
401
- // Since this is a custom object, capture the string tag to determing its type.
406
+ // Since this is a custom object, capture the string tag to determining its type.
402
407
  // This is reasonably performant in modern environments like v8 and SpiderMonkey.
403
408
  const tag = toString.call(a);
404
409
  const supportedComparator = supportedComparatorMap[tag];
405
410
  if (supportedComparator) {
406
411
  return supportedComparator(a, b, state);
407
412
  }
408
- const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, tag);
413
+ const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, state, tag);
409
414
  if (unsupportedCustomComparator) {
410
415
  return unsupportedCustomComparator(a, b, state);
411
416
  }
@@ -430,9 +435,9 @@ function createEqualityComparatorConfig({ circular, createCustomConfig, strict,
430
435
  areDataViewsEqual,
431
436
  areDatesEqual: areDatesEqual,
432
437
  areErrorsEqual: areErrorsEqual,
433
- areFunctionsEqual: areFunctionsEqual,
438
+ areFunctionsEqual: strictEqual,
434
439
  areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
435
- areNumbersEqual: areNumbersEqual,
440
+ areNumbersEqual: sameValueEqual,
436
441
  areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
437
442
  arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
438
443
  areRegExpsEqual: areRegExpsEqual,
@@ -512,6 +517,7 @@ function createSupportedComparatorMap({ areArrayBuffersEqual, areArraysEqual, ar
512
517
  '[object Arguments]': areObjectsEqual,
513
518
  '[object Array]': areArraysEqual,
514
519
  '[object ArrayBuffer]': areArrayBuffersEqual,
520
+ '[object AsyncGeneratorFunction]': areFunctionsEqual,
515
521
  '[object BigInt]': areNumbersEqual,
516
522
  '[object BigInt64Array]': areTypedArraysEqual,
517
523
  '[object BigUint64Array]': areTypedArraysEqual,
@@ -626,4 +632,5 @@ exports.shallowEqual = shallowEqual;
626
632
  exports.strictCircularDeepEqual = strictCircularDeepEqual;
627
633
  exports.strictCircularShallowEqual = strictCircularShallowEqual;
628
634
  exports.strictDeepEqual = strictDeepEqual;
635
+ exports.strictEqual = strictEqual;
629
636
  exports.strictShallowEqual = strictShallowEqual;
@@ -27,92 +27,75 @@ interface State<Meta> {
27
27
  */
28
28
  readonly strict: boolean;
29
29
  }
30
- interface CircularState<Meta> extends State<Meta> {
31
- readonly cache: Cache<any, any>;
32
- }
33
- interface DefaultState<Meta> extends State<Meta> {
34
- readonly cache: undefined;
35
- }
36
- interface Dictionary<Value = any> {
37
- [key: string | symbol]: Value;
38
- $$typeof?: any;
39
- }
40
30
  interface ComparatorConfig<Meta> {
41
31
  /**
42
32
  * Whether the array buffers passed are equal in value. In strict mode, this includes
43
33
  * additional properties added to the array.
44
34
  */
45
- areArrayBuffersEqual: TypeEqualityComparator<any, Meta>;
35
+ areArrayBuffersEqual: EqualityComparator<Meta>;
46
36
  /**
47
37
  * Whether the arrays passed are equal in value. In strict mode, this includes
48
38
  * additional properties added to the array.
49
39
  */
50
- areArraysEqual: TypeEqualityComparator<any, Meta>;
40
+ areArraysEqual: EqualityComparator<Meta>;
51
41
  /**
52
42
  * Whether the data views passed are equal in value.
53
43
  */
54
- areDataViewsEqual: TypeEqualityComparator<any, Meta>;
44
+ areDataViewsEqual: EqualityComparator<Meta>;
55
45
  /**
56
46
  * Whether the dates passed are equal in value.
57
47
  */
58
- areDatesEqual: TypeEqualityComparator<any, Meta>;
48
+ areDatesEqual: EqualityComparator<Meta>;
59
49
  /**
60
50
  * Whether the errors passed are equal in value.
61
51
  */
62
- areErrorsEqual: TypeEqualityComparator<any, Meta>;
52
+ areErrorsEqual: EqualityComparator<Meta>;
63
53
  /**
64
54
  * Whether the functions passed are equal in value.
65
55
  */
66
- areFunctionsEqual: TypeEqualityComparator<any, Meta>;
56
+ areFunctionsEqual: EqualityComparator<Meta>;
67
57
  /**
68
58
  * Whether the maps passed are equal in value. In strict mode, this includes
69
59
  * additional properties added to the map.
70
60
  */
71
- areMapsEqual: TypeEqualityComparator<any, Meta>;
61
+ areMapsEqual: EqualityComparator<Meta>;
72
62
  /**
73
63
  * Whether the numbers passed are equal in value.
74
64
  */
75
- areNumbersEqual: TypeEqualityComparator<any, Meta>;
65
+ areNumbersEqual: EqualityComparator<Meta>;
76
66
  /**
77
67
  * Whether the objects passed are equal in value. In strict mode, this includes
78
68
  * non-enumerable properties added to the map, as well as symbol properties.
79
69
  */
80
- areObjectsEqual: TypeEqualityComparator<any, Meta>;
70
+ areObjectsEqual: EqualityComparator<Meta>;
81
71
  /**
82
72
  * Whether the primitive wrappers passed are equal in value.
83
73
  */
84
- arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
74
+ arePrimitiveWrappersEqual: EqualityComparator<Meta>;
85
75
  /**
86
76
  * Whether the regexps passed are equal in value.
87
77
  */
88
- areRegExpsEqual: TypeEqualityComparator<any, Meta>;
78
+ areRegExpsEqual: EqualityComparator<Meta>;
89
79
  /**
90
80
  * Whether the sets passed are equal in value. In strict mode, this includes
91
81
  * additional properties added to the set.
92
82
  */
93
- areSetsEqual: TypeEqualityComparator<any, Meta>;
83
+ areSetsEqual: EqualityComparator<Meta>;
94
84
  /**
95
85
  * Whether the typed arrays passed are equal in value. In strict mode, this includes
96
86
  * additional properties added to the typed array.
97
87
  */
98
- areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
88
+ areTypedArraysEqual: EqualityComparator<Meta>;
99
89
  /**
100
90
  * Whether the URLs passed are equal in value.
101
91
  */
102
- areUrlsEqual: TypeEqualityComparator<any, Meta>;
92
+ areUrlsEqual: EqualityComparator<Meta>;
103
93
  /**
104
94
  * Get a custom comparator based on the objects passed.
105
95
  */
106
- getUnsupportedCustomComparator: ((a: any, b: any, tag: string) => TypeEqualityComparator<any, Meta> | undefined) | undefined;
96
+ getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
107
97
  }
108
- type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
109
- type CreateState<Meta> = () => {
110
- cache?: Cache<any, any> | undefined;
111
- meta?: Meta;
112
- };
113
- type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
114
- type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
115
- type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
98
+ type EqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
116
99
  type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
117
100
  type PrimitiveWrapper = Boolean | Number | String;
118
101
  /**
@@ -120,7 +103,6 @@ type PrimitiveWrapper = Boolean | Number | String;
120
103
  * classes.
121
104
  */
122
105
  type TypedArray = BigInt64Array | BigUint64Array | Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
123
- type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
124
106
  interface CustomEqualCreatorOptions<Meta> {
125
107
  /**
126
108
  * Whether circular references should be supported. It causes the
@@ -131,9 +113,9 @@ interface CustomEqualCreatorOptions<Meta> {
131
113
  /**
132
114
  * Create a custom configuration of type-specific equality comparators.
133
115
  * This receives the default configuration, which allows either replacement
134
- * or supersetting of the default methods.
116
+ * or a superset of the default methods.
135
117
  */
136
- createCustomConfig?: CreateCustomComparatorConfig<Meta>;
118
+ createCustomConfig?: (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
137
119
  /**
138
120
  * Create a custom internal comparator, which is used as an override to the
139
121
  * default entry point for nested value equality comparisons. This is often
@@ -146,7 +128,10 @@ interface CustomEqualCreatorOptions<Meta> {
146
128
  * Create a custom `state` object passed between the methods. This allows for
147
129
  * custom `cache` and/or `meta` values to be used.
148
130
  */
149
- createState?: CreateState<Meta>;
131
+ createState?: () => {
132
+ cache?: Cache<any, any> | undefined;
133
+ meta?: Meta;
134
+ };
150
135
  /**
151
136
  * Whether the equality comparison is strict, meaning it matches
152
137
  * all properties (including symbols and non-enumerable properties)
@@ -170,6 +155,16 @@ declare const sameValueEqual: (value1: any, value2: any) => boolean;
170
155
  * are either positive or negative zero.
171
156
  */
172
157
  declare function sameValueZeroEqual(a: any, b: any): boolean;
158
+ /**
159
+ * Whether the values passed are equal based on a
160
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
161
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
162
+ *
163
+ * @note
164
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
165
+ * two objects is used.
166
+ */
167
+ declare function strictEqual(a: any, b: any): boolean;
173
168
 
174
169
  /**
175
170
  * Whether the items passed are deeply-equal in value.
@@ -215,5 +210,5 @@ declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
215
210
  */
216
211
  declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;
217
212
 
218
- export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictShallowEqual };
219
- export type { AnyEqualityComparator, Cache, CircularState, ComparatorConfig, CreateCustomComparatorConfig, CreateState, CustomEqualCreatorOptions, DefaultState, Dictionary, EqualityComparator, EqualityComparatorCreator, InternalEqualityComparator, PrimitiveWrapper, State, TypeEqualityComparator, TypedArray };
213
+ export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictEqual, strictShallowEqual };
214
+ export type { Cache, ComparatorConfig, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator, PrimitiveWrapper, State, TypedArray };
@@ -27,92 +27,75 @@ interface State<Meta> {
27
27
  */
28
28
  readonly strict: boolean;
29
29
  }
30
- interface CircularState<Meta> extends State<Meta> {
31
- readonly cache: Cache<any, any>;
32
- }
33
- interface DefaultState<Meta> extends State<Meta> {
34
- readonly cache: undefined;
35
- }
36
- interface Dictionary<Value = any> {
37
- [key: string | symbol]: Value;
38
- $$typeof?: any;
39
- }
40
30
  interface ComparatorConfig<Meta> {
41
31
  /**
42
32
  * Whether the array buffers passed are equal in value. In strict mode, this includes
43
33
  * additional properties added to the array.
44
34
  */
45
- areArrayBuffersEqual: TypeEqualityComparator<any, Meta>;
35
+ areArrayBuffersEqual: EqualityComparator<Meta>;
46
36
  /**
47
37
  * Whether the arrays passed are equal in value. In strict mode, this includes
48
38
  * additional properties added to the array.
49
39
  */
50
- areArraysEqual: TypeEqualityComparator<any, Meta>;
40
+ areArraysEqual: EqualityComparator<Meta>;
51
41
  /**
52
42
  * Whether the data views passed are equal in value.
53
43
  */
54
- areDataViewsEqual: TypeEqualityComparator<any, Meta>;
44
+ areDataViewsEqual: EqualityComparator<Meta>;
55
45
  /**
56
46
  * Whether the dates passed are equal in value.
57
47
  */
58
- areDatesEqual: TypeEqualityComparator<any, Meta>;
48
+ areDatesEqual: EqualityComparator<Meta>;
59
49
  /**
60
50
  * Whether the errors passed are equal in value.
61
51
  */
62
- areErrorsEqual: TypeEqualityComparator<any, Meta>;
52
+ areErrorsEqual: EqualityComparator<Meta>;
63
53
  /**
64
54
  * Whether the functions passed are equal in value.
65
55
  */
66
- areFunctionsEqual: TypeEqualityComparator<any, Meta>;
56
+ areFunctionsEqual: EqualityComparator<Meta>;
67
57
  /**
68
58
  * Whether the maps passed are equal in value. In strict mode, this includes
69
59
  * additional properties added to the map.
70
60
  */
71
- areMapsEqual: TypeEqualityComparator<any, Meta>;
61
+ areMapsEqual: EqualityComparator<Meta>;
72
62
  /**
73
63
  * Whether the numbers passed are equal in value.
74
64
  */
75
- areNumbersEqual: TypeEqualityComparator<any, Meta>;
65
+ areNumbersEqual: EqualityComparator<Meta>;
76
66
  /**
77
67
  * Whether the objects passed are equal in value. In strict mode, this includes
78
68
  * non-enumerable properties added to the map, as well as symbol properties.
79
69
  */
80
- areObjectsEqual: TypeEqualityComparator<any, Meta>;
70
+ areObjectsEqual: EqualityComparator<Meta>;
81
71
  /**
82
72
  * Whether the primitive wrappers passed are equal in value.
83
73
  */
84
- arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
74
+ arePrimitiveWrappersEqual: EqualityComparator<Meta>;
85
75
  /**
86
76
  * Whether the regexps passed are equal in value.
87
77
  */
88
- areRegExpsEqual: TypeEqualityComparator<any, Meta>;
78
+ areRegExpsEqual: EqualityComparator<Meta>;
89
79
  /**
90
80
  * Whether the sets passed are equal in value. In strict mode, this includes
91
81
  * additional properties added to the set.
92
82
  */
93
- areSetsEqual: TypeEqualityComparator<any, Meta>;
83
+ areSetsEqual: EqualityComparator<Meta>;
94
84
  /**
95
85
  * Whether the typed arrays passed are equal in value. In strict mode, this includes
96
86
  * additional properties added to the typed array.
97
87
  */
98
- areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
88
+ areTypedArraysEqual: EqualityComparator<Meta>;
99
89
  /**
100
90
  * Whether the URLs passed are equal in value.
101
91
  */
102
- areUrlsEqual: TypeEqualityComparator<any, Meta>;
92
+ areUrlsEqual: EqualityComparator<Meta>;
103
93
  /**
104
94
  * Get a custom comparator based on the objects passed.
105
95
  */
106
- getUnsupportedCustomComparator: ((a: any, b: any, tag: string) => TypeEqualityComparator<any, Meta> | undefined) | undefined;
96
+ getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
107
97
  }
108
- type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
109
- type CreateState<Meta> = () => {
110
- cache?: Cache<any, any> | undefined;
111
- meta?: Meta;
112
- };
113
- type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
114
- type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
115
- type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
98
+ type EqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
116
99
  type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
117
100
  type PrimitiveWrapper = Boolean | Number | String;
118
101
  /**
@@ -120,7 +103,6 @@ type PrimitiveWrapper = Boolean | Number | String;
120
103
  * classes.
121
104
  */
122
105
  type TypedArray = BigInt64Array | BigUint64Array | Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
123
- type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
124
106
  interface CustomEqualCreatorOptions<Meta> {
125
107
  /**
126
108
  * Whether circular references should be supported. It causes the
@@ -131,9 +113,9 @@ interface CustomEqualCreatorOptions<Meta> {
131
113
  /**
132
114
  * Create a custom configuration of type-specific equality comparators.
133
115
  * This receives the default configuration, which allows either replacement
134
- * or supersetting of the default methods.
116
+ * or a superset of the default methods.
135
117
  */
136
- createCustomConfig?: CreateCustomComparatorConfig<Meta>;
118
+ createCustomConfig?: (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
137
119
  /**
138
120
  * Create a custom internal comparator, which is used as an override to the
139
121
  * default entry point for nested value equality comparisons. This is often
@@ -146,7 +128,10 @@ interface CustomEqualCreatorOptions<Meta> {
146
128
  * Create a custom `state` object passed between the methods. This allows for
147
129
  * custom `cache` and/or `meta` values to be used.
148
130
  */
149
- createState?: CreateState<Meta>;
131
+ createState?: () => {
132
+ cache?: Cache<any, any> | undefined;
133
+ meta?: Meta;
134
+ };
150
135
  /**
151
136
  * Whether the equality comparison is strict, meaning it matches
152
137
  * all properties (including symbols and non-enumerable properties)
@@ -170,6 +155,16 @@ declare const sameValueEqual: (value1: any, value2: any) => boolean;
170
155
  * are either positive or negative zero.
171
156
  */
172
157
  declare function sameValueZeroEqual(a: any, b: any): boolean;
158
+ /**
159
+ * Whether the values passed are equal based on a
160
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
161
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
162
+ *
163
+ * @note
164
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
165
+ * two objects is used.
166
+ */
167
+ declare function strictEqual(a: any, b: any): boolean;
173
168
 
174
169
  /**
175
170
  * Whether the items passed are deeply-equal in value.
@@ -215,5 +210,5 @@ declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
215
210
  */
216
211
  declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;
217
212
 
218
- export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictShallowEqual };
219
- export type { AnyEqualityComparator, Cache, CircularState, ComparatorConfig, CreateCustomComparatorConfig, CreateState, CustomEqualCreatorOptions, DefaultState, Dictionary, EqualityComparator, EqualityComparatorCreator, InternalEqualityComparator, PrimitiveWrapper, State, TypeEqualityComparator, TypedArray };
213
+ export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictEqual, strictShallowEqual };
214
+ export type { Cache, ComparatorConfig, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator, PrimitiveWrapper, State, TypedArray };
package/dist/es/index.mjs CHANGED
@@ -38,7 +38,10 @@ function createIsCircular(areItemsEqual) {
38
38
  * not enumerable and symbol properties.
39
39
  */
40
40
  function getStrictProperties(object) {
41
- return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
41
+ const symbols = getOwnPropertySymbols(object);
42
+ return symbols.length
43
+ ? getOwnPropertyNames(object).concat(symbols)
44
+ : getOwnPropertyNames(object);
42
45
  }
43
46
  /**
44
47
  * Whether the object contains the property passed as an own property.
@@ -73,6 +76,18 @@ Object.is
73
76
  function sameValueZeroEqual(a, b) {
74
77
  return a === b || (a !== a && b !== b);
75
78
  }
79
+ /**
80
+ * Whether the values passed are equal based on a
81
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
82
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
83
+ *
84
+ * @note
85
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
86
+ * two objects is used.
87
+ */
88
+ function strictEqual(a, b) {
89
+ return a === b;
90
+ }
76
91
  /**
77
92
  * Whether the array buffers are equal in value.
78
93
  */
@@ -113,12 +128,6 @@ function areDatesEqual(a, b) {
113
128
  function areErrorsEqual(a, b) {
114
129
  return a.name === b.name && a.message === b.message && a.cause === b.cause && a.stack === b.stack;
115
130
  }
116
- /**
117
- * Whether the functions passed are equal in value.
118
- */
119
- function areFunctionsEqual(a, b) {
120
- return a === b;
121
- }
122
131
  /**
123
132
  * Whether the `Map`s are equal in value.
124
133
  */
@@ -130,7 +139,7 @@ function areMapsEqual(a, b, state) {
130
139
  if (!size) {
131
140
  return true;
132
141
  }
133
- const matchedIndices = new Array(size);
142
+ const matchedIndices = new Uint8Array(size);
134
143
  const aIterable = a.entries();
135
144
  let aResult;
136
145
  let bResult;
@@ -141,7 +150,7 @@ function areMapsEqual(a, b, state) {
141
150
  break;
142
151
  }
143
152
  const bIterable = b.entries();
144
- let hasMatch = false;
153
+ let hasMatch = 0;
145
154
  let matchIndex = 0;
146
155
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
147
156
  while ((bResult = bIterable.next())) {
@@ -156,7 +165,7 @@ function areMapsEqual(a, b, state) {
156
165
  const bEntry = bResult.value;
157
166
  if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state)
158
167
  && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
159
- hasMatch = matchedIndices[matchIndex] = true;
168
+ hasMatch = matchedIndices[matchIndex] = 1;
160
169
  break;
161
170
  }
162
171
  matchIndex++;
@@ -168,10 +177,6 @@ function areMapsEqual(a, b, state) {
168
177
  }
169
178
  return true;
170
179
  }
171
- /**
172
- * Whether the numbers are equal in value.
173
- */
174
- const areNumbersEqual = sameValueEqual;
175
180
  /**
176
181
  * Whether the objects are equal in value.
177
182
  */
@@ -249,7 +254,7 @@ function areSetsEqual(a, b, state) {
249
254
  if (!size) {
250
255
  return true;
251
256
  }
252
- const matchedIndices = new Array(size);
257
+ const matchedIndices = new Uint8Array(size);
253
258
  const aIterable = a.values();
254
259
  let aResult;
255
260
  let bResult;
@@ -259,7 +264,7 @@ function areSetsEqual(a, b, state) {
259
264
  break;
260
265
  }
261
266
  const bIterable = b.values();
262
- let hasMatch = false;
267
+ let hasMatch = 0;
263
268
  let matchIndex = 0;
264
269
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
265
270
  while ((bResult = bIterable.next())) {
@@ -268,7 +273,7 @@ function areSetsEqual(a, b, state) {
268
273
  }
269
274
  if (!matchedIndices[matchIndex]
270
275
  && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
271
- hasMatch = matchedIndices[matchIndex] = true;
276
+ hasMatch = matchedIndices[matchIndex] = 1;
272
277
  break;
273
278
  }
274
279
  matchIndex++;
@@ -283,8 +288,8 @@ function areSetsEqual(a, b, state) {
283
288
  * Whether the TypedArray instances are equal in value.
284
289
  */
285
290
  function areTypedArraysEqual(a, b) {
286
- let index = a.byteLength;
287
- if (b.byteLength !== index || a.byteOffset !== b.byteOffset) {
291
+ let index = a.length;
292
+ if (b.length !== index || a.byteOffset !== b.byteOffset) {
288
293
  return false;
289
294
  }
290
295
  while (index-- > 0) {
@@ -366,8 +371,8 @@ function createEqualityComparator(config) {
366
371
  // Try to fast-path equality checks for other complex object types in the
367
372
  // same realm to avoid capturing the string tag. Strict equality is used
368
373
  // instead of `instanceof` because it is more performant for the common
369
- // use-case. If someone is subclassing a native class, it will be handled
370
- // with the string tag comparison.
374
+ // use-case. If someone is creating a subclass from a native class, it will be
375
+ // handled with the string tag comparison.
371
376
  if (constructor === Object) {
372
377
  return areObjectsEqual(a, b, state);
373
378
  }
@@ -396,14 +401,14 @@ function createEqualityComparator(config) {
396
401
  if (Array.isArray(a)) {
397
402
  return areArraysEqual(a, b, state);
398
403
  }
399
- // Since this is a custom object, capture the string tag to determing its type.
404
+ // Since this is a custom object, capture the string tag to determining its type.
400
405
  // This is reasonably performant in modern environments like v8 and SpiderMonkey.
401
406
  const tag = toString.call(a);
402
407
  const supportedComparator = supportedComparatorMap[tag];
403
408
  if (supportedComparator) {
404
409
  return supportedComparator(a, b, state);
405
410
  }
406
- const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, tag);
411
+ const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, state, tag);
407
412
  if (unsupportedCustomComparator) {
408
413
  return unsupportedCustomComparator(a, b, state);
409
414
  }
@@ -428,9 +433,9 @@ function createEqualityComparatorConfig({ circular, createCustomConfig, strict,
428
433
  areDataViewsEqual,
429
434
  areDatesEqual: areDatesEqual,
430
435
  areErrorsEqual: areErrorsEqual,
431
- areFunctionsEqual: areFunctionsEqual,
436
+ areFunctionsEqual: strictEqual,
432
437
  areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
433
- areNumbersEqual: areNumbersEqual,
438
+ areNumbersEqual: sameValueEqual,
434
439
  areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
435
440
  arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
436
441
  areRegExpsEqual: areRegExpsEqual,
@@ -510,6 +515,7 @@ function createSupportedComparatorMap({ areArrayBuffersEqual, areArraysEqual, ar
510
515
  '[object Arguments]': areObjectsEqual,
511
516
  '[object Array]': areArraysEqual,
512
517
  '[object ArrayBuffer]': areArrayBuffersEqual,
518
+ '[object AsyncGeneratorFunction]': areFunctionsEqual,
513
519
  '[object BigInt]': areNumbersEqual,
514
520
  '[object BigInt64Array]': areTypedArraysEqual,
515
521
  '[object BigUint64Array]': areTypedArraysEqual,
@@ -614,4 +620,4 @@ function createCustomEqual(options = {}) {
614
620
  return createIsEqual({ circular, comparator, createState, equals, strict });
615
621
  }
616
622
 
617
- export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictShallowEqual };
623
+ export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictEqual, strictShallowEqual };
package/index.d.ts CHANGED
@@ -27,92 +27,75 @@ interface State<Meta> {
27
27
  */
28
28
  readonly strict: boolean;
29
29
  }
30
- interface CircularState<Meta> extends State<Meta> {
31
- readonly cache: Cache<any, any>;
32
- }
33
- interface DefaultState<Meta> extends State<Meta> {
34
- readonly cache: undefined;
35
- }
36
- interface Dictionary<Value = any> {
37
- [key: string | symbol]: Value;
38
- $$typeof?: any;
39
- }
40
30
  interface ComparatorConfig<Meta> {
41
31
  /**
42
32
  * Whether the array buffers passed are equal in value. In strict mode, this includes
43
33
  * additional properties added to the array.
44
34
  */
45
- areArrayBuffersEqual: TypeEqualityComparator<any, Meta>;
35
+ areArrayBuffersEqual: EqualityComparator<Meta>;
46
36
  /**
47
37
  * Whether the arrays passed are equal in value. In strict mode, this includes
48
38
  * additional properties added to the array.
49
39
  */
50
- areArraysEqual: TypeEqualityComparator<any, Meta>;
40
+ areArraysEqual: EqualityComparator<Meta>;
51
41
  /**
52
42
  * Whether the data views passed are equal in value.
53
43
  */
54
- areDataViewsEqual: TypeEqualityComparator<any, Meta>;
44
+ areDataViewsEqual: EqualityComparator<Meta>;
55
45
  /**
56
46
  * Whether the dates passed are equal in value.
57
47
  */
58
- areDatesEqual: TypeEqualityComparator<any, Meta>;
48
+ areDatesEqual: EqualityComparator<Meta>;
59
49
  /**
60
50
  * Whether the errors passed are equal in value.
61
51
  */
62
- areErrorsEqual: TypeEqualityComparator<any, Meta>;
52
+ areErrorsEqual: EqualityComparator<Meta>;
63
53
  /**
64
54
  * Whether the functions passed are equal in value.
65
55
  */
66
- areFunctionsEqual: TypeEqualityComparator<any, Meta>;
56
+ areFunctionsEqual: EqualityComparator<Meta>;
67
57
  /**
68
58
  * Whether the maps passed are equal in value. In strict mode, this includes
69
59
  * additional properties added to the map.
70
60
  */
71
- areMapsEqual: TypeEqualityComparator<any, Meta>;
61
+ areMapsEqual: EqualityComparator<Meta>;
72
62
  /**
73
63
  * Whether the numbers passed are equal in value.
74
64
  */
75
- areNumbersEqual: TypeEqualityComparator<any, Meta>;
65
+ areNumbersEqual: EqualityComparator<Meta>;
76
66
  /**
77
67
  * Whether the objects passed are equal in value. In strict mode, this includes
78
68
  * non-enumerable properties added to the map, as well as symbol properties.
79
69
  */
80
- areObjectsEqual: TypeEqualityComparator<any, Meta>;
70
+ areObjectsEqual: EqualityComparator<Meta>;
81
71
  /**
82
72
  * Whether the primitive wrappers passed are equal in value.
83
73
  */
84
- arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
74
+ arePrimitiveWrappersEqual: EqualityComparator<Meta>;
85
75
  /**
86
76
  * Whether the regexps passed are equal in value.
87
77
  */
88
- areRegExpsEqual: TypeEqualityComparator<any, Meta>;
78
+ areRegExpsEqual: EqualityComparator<Meta>;
89
79
  /**
90
80
  * Whether the sets passed are equal in value. In strict mode, this includes
91
81
  * additional properties added to the set.
92
82
  */
93
- areSetsEqual: TypeEqualityComparator<any, Meta>;
83
+ areSetsEqual: EqualityComparator<Meta>;
94
84
  /**
95
85
  * Whether the typed arrays passed are equal in value. In strict mode, this includes
96
86
  * additional properties added to the typed array.
97
87
  */
98
- areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
88
+ areTypedArraysEqual: EqualityComparator<Meta>;
99
89
  /**
100
90
  * Whether the URLs passed are equal in value.
101
91
  */
102
- areUrlsEqual: TypeEqualityComparator<any, Meta>;
92
+ areUrlsEqual: EqualityComparator<Meta>;
103
93
  /**
104
94
  * Get a custom comparator based on the objects passed.
105
95
  */
106
- getUnsupportedCustomComparator: ((a: any, b: any, tag: string) => TypeEqualityComparator<any, Meta> | undefined) | undefined;
96
+ getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
107
97
  }
108
- type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
109
- type CreateState<Meta> = () => {
110
- cache?: Cache<any, any> | undefined;
111
- meta?: Meta;
112
- };
113
- type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
114
- type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
115
- type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
98
+ type EqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
116
99
  type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
117
100
  type PrimitiveWrapper = Boolean | Number | String;
118
101
  /**
@@ -120,7 +103,6 @@ type PrimitiveWrapper = Boolean | Number | String;
120
103
  * classes.
121
104
  */
122
105
  type TypedArray = BigInt64Array | BigUint64Array | Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
123
- type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
124
106
  interface CustomEqualCreatorOptions<Meta> {
125
107
  /**
126
108
  * Whether circular references should be supported. It causes the
@@ -131,9 +113,9 @@ interface CustomEqualCreatorOptions<Meta> {
131
113
  /**
132
114
  * Create a custom configuration of type-specific equality comparators.
133
115
  * This receives the default configuration, which allows either replacement
134
- * or supersetting of the default methods.
116
+ * or a superset of the default methods.
135
117
  */
136
- createCustomConfig?: CreateCustomComparatorConfig<Meta>;
118
+ createCustomConfig?: (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
137
119
  /**
138
120
  * Create a custom internal comparator, which is used as an override to the
139
121
  * default entry point for nested value equality comparisons. This is often
@@ -146,7 +128,10 @@ interface CustomEqualCreatorOptions<Meta> {
146
128
  * Create a custom `state` object passed between the methods. This allows for
147
129
  * custom `cache` and/or `meta` values to be used.
148
130
  */
149
- createState?: CreateState<Meta>;
131
+ createState?: () => {
132
+ cache?: Cache<any, any> | undefined;
133
+ meta?: Meta;
134
+ };
150
135
  /**
151
136
  * Whether the equality comparison is strict, meaning it matches
152
137
  * all properties (including symbols and non-enumerable properties)
@@ -170,6 +155,16 @@ declare const sameValueEqual: (value1: any, value2: any) => boolean;
170
155
  * are either positive or negative zero.
171
156
  */
172
157
  declare function sameValueZeroEqual(a: any, b: any): boolean;
158
+ /**
159
+ * Whether the values passed are equal based on a
160
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
161
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
162
+ *
163
+ * @note
164
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
165
+ * two objects is used.
166
+ */
167
+ declare function strictEqual(a: any, b: any): boolean;
173
168
 
174
169
  /**
175
170
  * Whether the items passed are deeply-equal in value.
@@ -215,5 +210,5 @@ declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
215
210
  */
216
211
  declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;
217
212
 
218
- export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictShallowEqual };
219
- export type { AnyEqualityComparator, Cache, CircularState, ComparatorConfig, CreateCustomComparatorConfig, CreateState, CustomEqualCreatorOptions, DefaultState, Dictionary, EqualityComparator, EqualityComparatorCreator, InternalEqualityComparator, PrimitiveWrapper, State, TypeEqualityComparator, TypedArray };
213
+ export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictEqual, strictShallowEqual };
214
+ export type { Cache, ComparatorConfig, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator, PrimitiveWrapper, State, TypedArray };
package/package.json CHANGED
@@ -7,42 +7,42 @@
7
7
  "bugs": {
8
8
  "url": "https://github.com/planttheidea/fast-equals/issues"
9
9
  },
10
- "description": "A blazing fast equality comparison, either shallow or deep",
10
+ "description": "A blazing-fast equality comparison utility for a variety of use-cases",
11
11
  "devDependencies": {
12
12
  "@planttheidea/build-tools": "^2.0.0",
13
- "@types/lodash": "^4.17.21",
14
- "@types/node": "^24.10.4",
13
+ "@types/lodash": "^4.17.24",
14
+ "@types/node": "^24.13.2",
15
15
  "@types/ramda": "^0.31.1",
16
- "@types/react": "^19.2.7",
16
+ "@types/react": "^19.2.17",
17
17
  "@types/react-dom": "^19.2.3",
18
- "@typescript-eslint/eslint-plugin": "^8.50.0",
19
- "@typescript-eslint/parser": "^8.50.0",
20
- "@vitest/coverage-v8": "^4.0.15",
18
+ "@typescript-eslint/eslint-plugin": "^8.63.0",
19
+ "@typescript-eslint/parser": "^8.63.0",
20
+ "@vitest/coverage-v8": "^4.1.10",
21
21
  "cli-table3": "^0.6.5",
22
22
  "decircularize": "^1.0.0",
23
23
  "deep-eql": "^5.0.2",
24
24
  "deep-equal": "^2.2.3",
25
25
  "dequal": "^2.0.3",
26
- "eslint": "^9.39.2",
26
+ "eslint": "^9.39.4",
27
27
  "eslint-friendly-formatter": "^4.0.1",
28
28
  "eslint-plugin-import": "^2.32.0",
29
29
  "fast-deep-equal": "^3.1.3",
30
30
  "fast-glob": "^3.3.3",
31
- "lodash": "^4.17.21",
31
+ "lodash": "^4.18.1",
32
32
  "nano-equal": "^2.0.2",
33
- "prettier": "^3.7.4",
34
- "react": "^19.2.3",
35
- "react-dom": "^19.2.3",
33
+ "prettier": "^3.9.4",
34
+ "react": "^19.2.7",
35
+ "react-dom": "^19.2.7",
36
36
  "react-fast-compare": "^3.2.2",
37
- "release-it": "^19.1.0",
38
- "rollup": "^4.53.5",
37
+ "release-it": "^19.2.4",
38
+ "rollup": "^4.62.2",
39
39
  "shallow-equal-fuzzy": "^0.0.2",
40
- "tinybench": "^6.0.0",
40
+ "tinybench": "^6.0.2",
41
41
  "typescript": "^5.9.3",
42
- "typescript-eslint": "^8.50.0",
43
- "underscore": "^1.13.7",
44
- "vite": "^7.3.0",
45
- "vitest": "^4.0.15"
42
+ "typescript-eslint": "^8.63.0",
43
+ "underscore": "^1.13.8",
44
+ "vite": "^7.3.6",
45
+ "vitest": "^4.1.10"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=6.0.0"
@@ -109,5 +109,5 @@
109
109
  "sideEffects": false,
110
110
  "type": "module",
111
111
  "types": "./index.d.ts",
112
- "version": "6.0.0-rc.1"
112
+ "version": "6.0.1"
113
113
  }