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 +83 -84
- package/dist/cjs/index.cjs +32 -25
- package/dist/cjs/index.d.cts +34 -39
- package/dist/es/index.d.mts +34 -39
- package/dist/es/index.mjs +32 -26
- package/index.d.ts +34 -39
- package/package.json +20 -20
package/README.md
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
> fast-equals
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
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
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
areDataViewsEqual:
|
|
334
|
-
areDatesEqual:
|
|
335
|
-
areErrorsEqual:
|
|
336
|
-
areFunctionsEqual:
|
|
337
|
-
areMapsEqual:
|
|
338
|
-
areNumbersEqual:
|
|
339
|
-
areObjectsEqual:
|
|
340
|
-
arePrimitiveWrappersEqual:
|
|
341
|
-
areRegExpsEqual:
|
|
342
|
-
areSetsEqual:
|
|
343
|
-
areTypedArraysEqual:
|
|
344
|
-
areUrlsEqual:
|
|
345
|
-
getUnsupportedCustomComparator: <Type>(a: Type, b: Type, tag: string) =>
|
|
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
|
|
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
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -40,7 +40,10 @@ function createIsCircular(areItemsEqual) {
|
|
|
40
40
|
* not enumerable and symbol properties.
|
|
41
41
|
*/
|
|
42
42
|
function getStrictProperties(object) {
|
|
43
|
-
|
|
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
|
|
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 =
|
|
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] =
|
|
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
|
|
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 =
|
|
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] =
|
|
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.
|
|
289
|
-
if (b.
|
|
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
|
|
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
|
|
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:
|
|
438
|
+
areFunctionsEqual: strictEqual,
|
|
434
439
|
areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
|
|
435
|
-
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;
|
package/dist/cjs/index.d.cts
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:
|
|
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:
|
|
40
|
+
areArraysEqual: EqualityComparator<Meta>;
|
|
51
41
|
/**
|
|
52
42
|
* Whether the data views passed are equal in value.
|
|
53
43
|
*/
|
|
54
|
-
areDataViewsEqual:
|
|
44
|
+
areDataViewsEqual: EqualityComparator<Meta>;
|
|
55
45
|
/**
|
|
56
46
|
* Whether the dates passed are equal in value.
|
|
57
47
|
*/
|
|
58
|
-
areDatesEqual:
|
|
48
|
+
areDatesEqual: EqualityComparator<Meta>;
|
|
59
49
|
/**
|
|
60
50
|
* Whether the errors passed are equal in value.
|
|
61
51
|
*/
|
|
62
|
-
areErrorsEqual:
|
|
52
|
+
areErrorsEqual: EqualityComparator<Meta>;
|
|
63
53
|
/**
|
|
64
54
|
* Whether the functions passed are equal in value.
|
|
65
55
|
*/
|
|
66
|
-
areFunctionsEqual:
|
|
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:
|
|
61
|
+
areMapsEqual: EqualityComparator<Meta>;
|
|
72
62
|
/**
|
|
73
63
|
* Whether the numbers passed are equal in value.
|
|
74
64
|
*/
|
|
75
|
-
areNumbersEqual:
|
|
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:
|
|
70
|
+
areObjectsEqual: EqualityComparator<Meta>;
|
|
81
71
|
/**
|
|
82
72
|
* Whether the primitive wrappers passed are equal in value.
|
|
83
73
|
*/
|
|
84
|
-
arePrimitiveWrappersEqual:
|
|
74
|
+
arePrimitiveWrappersEqual: EqualityComparator<Meta>;
|
|
85
75
|
/**
|
|
86
76
|
* Whether the regexps passed are equal in value.
|
|
87
77
|
*/
|
|
88
|
-
areRegExpsEqual:
|
|
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:
|
|
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:
|
|
88
|
+
areTypedArraysEqual: EqualityComparator<Meta>;
|
|
99
89
|
/**
|
|
100
90
|
* Whether the URLs passed are equal in value.
|
|
101
91
|
*/
|
|
102
|
-
areUrlsEqual:
|
|
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) =>
|
|
96
|
+
getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
|
|
107
97
|
}
|
|
108
|
-
type
|
|
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
|
|
116
|
+
* or a superset of the default methods.
|
|
135
117
|
*/
|
|
136
|
-
createCustomConfig?:
|
|
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?:
|
|
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 {
|
|
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.d.mts
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:
|
|
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:
|
|
40
|
+
areArraysEqual: EqualityComparator<Meta>;
|
|
51
41
|
/**
|
|
52
42
|
* Whether the data views passed are equal in value.
|
|
53
43
|
*/
|
|
54
|
-
areDataViewsEqual:
|
|
44
|
+
areDataViewsEqual: EqualityComparator<Meta>;
|
|
55
45
|
/**
|
|
56
46
|
* Whether the dates passed are equal in value.
|
|
57
47
|
*/
|
|
58
|
-
areDatesEqual:
|
|
48
|
+
areDatesEqual: EqualityComparator<Meta>;
|
|
59
49
|
/**
|
|
60
50
|
* Whether the errors passed are equal in value.
|
|
61
51
|
*/
|
|
62
|
-
areErrorsEqual:
|
|
52
|
+
areErrorsEqual: EqualityComparator<Meta>;
|
|
63
53
|
/**
|
|
64
54
|
* Whether the functions passed are equal in value.
|
|
65
55
|
*/
|
|
66
|
-
areFunctionsEqual:
|
|
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:
|
|
61
|
+
areMapsEqual: EqualityComparator<Meta>;
|
|
72
62
|
/**
|
|
73
63
|
* Whether the numbers passed are equal in value.
|
|
74
64
|
*/
|
|
75
|
-
areNumbersEqual:
|
|
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:
|
|
70
|
+
areObjectsEqual: EqualityComparator<Meta>;
|
|
81
71
|
/**
|
|
82
72
|
* Whether the primitive wrappers passed are equal in value.
|
|
83
73
|
*/
|
|
84
|
-
arePrimitiveWrappersEqual:
|
|
74
|
+
arePrimitiveWrappersEqual: EqualityComparator<Meta>;
|
|
85
75
|
/**
|
|
86
76
|
* Whether the regexps passed are equal in value.
|
|
87
77
|
*/
|
|
88
|
-
areRegExpsEqual:
|
|
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:
|
|
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:
|
|
88
|
+
areTypedArraysEqual: EqualityComparator<Meta>;
|
|
99
89
|
/**
|
|
100
90
|
* Whether the URLs passed are equal in value.
|
|
101
91
|
*/
|
|
102
|
-
areUrlsEqual:
|
|
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) =>
|
|
96
|
+
getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
|
|
107
97
|
}
|
|
108
|
-
type
|
|
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
|
|
116
|
+
* or a superset of the default methods.
|
|
135
117
|
*/
|
|
136
|
-
createCustomConfig?:
|
|
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?:
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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] =
|
|
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
|
|
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 =
|
|
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] =
|
|
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.
|
|
287
|
-
if (b.
|
|
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
|
|
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
|
|
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:
|
|
436
|
+
areFunctionsEqual: strictEqual,
|
|
432
437
|
areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
|
|
433
|
-
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:
|
|
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:
|
|
40
|
+
areArraysEqual: EqualityComparator<Meta>;
|
|
51
41
|
/**
|
|
52
42
|
* Whether the data views passed are equal in value.
|
|
53
43
|
*/
|
|
54
|
-
areDataViewsEqual:
|
|
44
|
+
areDataViewsEqual: EqualityComparator<Meta>;
|
|
55
45
|
/**
|
|
56
46
|
* Whether the dates passed are equal in value.
|
|
57
47
|
*/
|
|
58
|
-
areDatesEqual:
|
|
48
|
+
areDatesEqual: EqualityComparator<Meta>;
|
|
59
49
|
/**
|
|
60
50
|
* Whether the errors passed are equal in value.
|
|
61
51
|
*/
|
|
62
|
-
areErrorsEqual:
|
|
52
|
+
areErrorsEqual: EqualityComparator<Meta>;
|
|
63
53
|
/**
|
|
64
54
|
* Whether the functions passed are equal in value.
|
|
65
55
|
*/
|
|
66
|
-
areFunctionsEqual:
|
|
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:
|
|
61
|
+
areMapsEqual: EqualityComparator<Meta>;
|
|
72
62
|
/**
|
|
73
63
|
* Whether the numbers passed are equal in value.
|
|
74
64
|
*/
|
|
75
|
-
areNumbersEqual:
|
|
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:
|
|
70
|
+
areObjectsEqual: EqualityComparator<Meta>;
|
|
81
71
|
/**
|
|
82
72
|
* Whether the primitive wrappers passed are equal in value.
|
|
83
73
|
*/
|
|
84
|
-
arePrimitiveWrappersEqual:
|
|
74
|
+
arePrimitiveWrappersEqual: EqualityComparator<Meta>;
|
|
85
75
|
/**
|
|
86
76
|
* Whether the regexps passed are equal in value.
|
|
87
77
|
*/
|
|
88
|
-
areRegExpsEqual:
|
|
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:
|
|
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:
|
|
88
|
+
areTypedArraysEqual: EqualityComparator<Meta>;
|
|
99
89
|
/**
|
|
100
90
|
* Whether the URLs passed are equal in value.
|
|
101
91
|
*/
|
|
102
|
-
areUrlsEqual:
|
|
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) =>
|
|
96
|
+
getUnsupportedCustomComparator: ((a: any, b: any, state: State<Meta>, tag: string) => EqualityComparator<Meta> | undefined) | undefined;
|
|
107
97
|
}
|
|
108
|
-
type
|
|
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
|
|
116
|
+
* or a superset of the default methods.
|
|
135
117
|
*/
|
|
136
|
-
createCustomConfig?:
|
|
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?:
|
|
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 {
|
|
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
|
|
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.
|
|
14
|
-
"@types/node": "^24.
|
|
13
|
+
"@types/lodash": "^4.17.24",
|
|
14
|
+
"@types/node": "^24.13.2",
|
|
15
15
|
"@types/ramda": "^0.31.1",
|
|
16
|
-
"@types/react": "^19.2.
|
|
16
|
+
"@types/react": "^19.2.17",
|
|
17
17
|
"@types/react-dom": "^19.2.3",
|
|
18
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
19
|
-
"@typescript-eslint/parser": "^8.
|
|
20
|
-
"@vitest/coverage-v8": "^4.
|
|
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.
|
|
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.
|
|
31
|
+
"lodash": "^4.18.1",
|
|
32
32
|
"nano-equal": "^2.0.2",
|
|
33
|
-
"prettier": "^3.
|
|
34
|
-
"react": "^19.2.
|
|
35
|
-
"react-dom": "^19.2.
|
|
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.
|
|
38
|
-
"rollup": "^4.
|
|
37
|
+
"release-it": "^19.2.4",
|
|
38
|
+
"rollup": "^4.62.2",
|
|
39
39
|
"shallow-equal-fuzzy": "^0.0.2",
|
|
40
|
-
"tinybench": "^6.0.
|
|
40
|
+
"tinybench": "^6.0.2",
|
|
41
41
|
"typescript": "^5.9.3",
|
|
42
|
-
"typescript-eslint": "^8.
|
|
43
|
-
"underscore": "^1.13.
|
|
44
|
-
"vite": "^7.3.
|
|
45
|
-
"vitest": "^4.
|
|
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.
|
|
112
|
+
"version": "6.0.1"
|
|
113
113
|
}
|