fast-equals 5.0.0-beta.4 → 5.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/README.md +30 -34
- package/dist/cjs/index.cjs +169 -141
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/types/comparator.d.ts +20 -3
- package/dist/cjs/types/equals.d.ts +5 -2
- package/dist/cjs/types/index.d.ts +9 -9
- package/dist/cjs/types/internalTypes.d.ts +16 -12
- package/dist/cjs/types/utils.d.ts +1 -7
- package/dist/esm/index.mjs +169 -141
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/types/comparator.d.ts +20 -3
- package/dist/esm/types/equals.d.ts +5 -2
- package/dist/esm/types/index.d.ts +9 -9
- package/dist/esm/types/internalTypes.d.ts +16 -12
- package/dist/esm/types/utils.d.ts +1 -7
- package/dist/min/index.js +1 -1
- package/dist/min/types/comparator.d.ts +20 -3
- package/dist/min/types/equals.d.ts +5 -2
- package/dist/min/types/index.d.ts +9 -9
- package/dist/min/types/internalTypes.d.ts +16 -12
- package/dist/min/types/utils.d.ts +1 -7
- package/dist/umd/index.js +169 -141
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/types/comparator.d.ts +20 -3
- package/dist/umd/types/equals.d.ts +5 -2
- package/dist/umd/types/index.d.ts +9 -9
- package/dist/umd/types/internalTypes.d.ts +16 -12
- package/dist/umd/types/utils.d.ts +1 -7
- package/package.json +7 -7
- package/recipes/legacy-circular-equal-support.md +3 -2
- package/recipes/legacy-regexp-support.md +2 -3
- package/recipes/non-standard-properties.md +4 -2
- package/src/comparator.ts +131 -35
- package/src/equals.ts +97 -63
- package/src/index.ts +21 -65
- package/src/internalTypes.ts +20 -16
- package/src/utils.ts +2 -31
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
### Breaking changes
|
|
6
6
|
|
|
7
|
+
#### `constructor` equality now required
|
|
8
|
+
|
|
9
|
+
To align with other implementations common in the community, but also to be more functionally correct, the two objects being compared now must have equal `constructor`s.
|
|
10
|
+
|
|
11
|
+
#### `Map` / `Set` comparisons no longer support IE11
|
|
12
|
+
|
|
13
|
+
In previous verisons, `.forEach()` was used to ensure that support for `Symbol` was not required, as IE11 did not have `Symbol` and therefore both `Map` and `Set` did not have iterator-based methods such as `.values()` or `.entries()`. Since IE11 is no longer a supported browser, and support for those methods is present in all browsers and Node for quite a while, the comparison has moved to use these methods. This results in a ~20% performance increase.
|
|
14
|
+
|
|
7
15
|
#### `createCustomEqual` contract has changed
|
|
8
16
|
|
|
9
|
-
To better facilitate strict comparisons, but also to allow for `meta` use separate from caching, the contract for `createCustomEqual` has changed. See the [README documentation](./README.md#createcustomequal) for more details
|
|
17
|
+
To better facilitate strict comparisons, but also to allow for `meta` use separate from caching, the contract for `createCustomEqual` has changed. See the [README documentation](./README.md#createcustomequal) for more details, but froma high-level:
|
|
18
|
+
|
|
19
|
+
- `meta` is no longer passed through to equality comparators, but rather a general `state` object which contains `meta`
|
|
20
|
+
- `cache` now also lives on the `state` object, which allows for use of the `meta` property separate from but in parallel with the circular cache
|
|
21
|
+
- `equals` is now on `state`, which prevents the need to pass through the separate `isEqual` method for the equality comparator
|
|
10
22
|
|
|
11
23
|
#### `createCustomCircularEqual` has been removed
|
|
12
24
|
|
package/README.md
CHANGED
|
@@ -4,18 +4,21 @@
|
|
|
4
4
|
<img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/>
|
|
5
5
|
<img src="https://img.shields.io/badge/license-MIT-blue.svg"/>
|
|
6
6
|
|
|
7
|
-
Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.
|
|
7
|
+
Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed, while also maintaining a high degree of flexibility for various implementation use-cases. It has no dependencies, and is ~1.8kB when minified and gzipped.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The following types are handled out-of-the-box:
|
|
10
10
|
|
|
11
|
-
- `
|
|
11
|
+
- Plain objects (including `react` elements and `Arguments`)
|
|
12
|
+
- Arrays
|
|
13
|
+
- Typed Arrays
|
|
12
14
|
- `Date` objects
|
|
13
15
|
- `RegExp` objects
|
|
14
16
|
- `Map` / `Set` iterables
|
|
15
17
|
- `Promise` objects
|
|
16
|
-
- `
|
|
18
|
+
- Primitive wrappers (`new Boolean()` / `new Number()` / `new String()`)
|
|
19
|
+
- Custom class instances, including subclasses of native classes
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
Methods are available for deep, shallow, or referential equality comparison. In addition, you can opt into support for circular objects, or performing a "strict" comparison with unconventional property definition, or both. You can also customize any specific type comparison based on your application's use-cases.
|
|
19
22
|
|
|
20
23
|
## Table of contents
|
|
21
24
|
|
|
@@ -162,7 +165,6 @@ console.log(circularShallowEqual(array, [array])); // false
|
|
|
162
165
|
|
|
163
166
|
Performs the same comparison as `deepEqual` but performs a strict comparison of the objects. In this includes:
|
|
164
167
|
|
|
165
|
-
- Checking constructors match
|
|
166
168
|
- Checking non-enumerable properties in object comparisons
|
|
167
169
|
- Checking full descriptor of properties on the object to match
|
|
168
170
|
- Checking non-index properties on arrays
|
|
@@ -269,24 +271,13 @@ Creates a custom equality comparator that will be used on nested values in the o
|
|
|
269
271
|
The signature is as follows:
|
|
270
272
|
|
|
271
273
|
```ts
|
|
272
|
-
interface
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
interface DefaultState<Meta> {
|
|
277
|
-
readonly cache: undefined | BaseCircular;
|
|
278
|
-
readonly equals: InternalEqualityComparator<Meta>;
|
|
279
|
-
meta: Meta;
|
|
280
|
-
readonly strict: boolean;
|
|
274
|
+
interface Cache<Key extends object, Value> {
|
|
275
|
+
delete(key: Key): boolean;
|
|
276
|
+
get(key: Key): Value | undefined;
|
|
277
|
+
set(key: Key, value: any): any;
|
|
281
278
|
}
|
|
282
279
|
|
|
283
|
-
|
|
284
|
-
a: A,
|
|
285
|
-
b: B,
|
|
286
|
-
state: State<Meta>,
|
|
287
|
-
) => boolean;
|
|
288
|
-
|
|
289
|
-
interface CreateComparatorCreatorOptions<Meta> {
|
|
280
|
+
interface ComparatorConfig<Meta> {
|
|
290
281
|
areArraysEqual: TypeEqualityComparator<any[], Meta>;
|
|
291
282
|
areDatesEqual: TypeEqualityComparator<Date, Meta>;
|
|
292
283
|
areMapsEqual: TypeEqualityComparator<Map<any, any>, Meta>;
|
|
@@ -300,20 +291,25 @@ interface CreateComparatorCreatorOptions<Meta> {
|
|
|
300
291
|
areTypedArraysEqual: TypeEqualityComparatory<TypedArray, Meta>;
|
|
301
292
|
}
|
|
302
293
|
|
|
303
|
-
|
|
294
|
+
function createCustomEqual<Meta>(options: {
|
|
304
295
|
circular?: boolean;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
296
|
+
createCustomConfig?: (
|
|
297
|
+
defaultConfig: ComparatorConfig<Meta>,
|
|
298
|
+
) => Partial<ComparatorConfig<Meta>>;
|
|
299
|
+
createInternalComparator?: (
|
|
300
|
+
compare: <A, B>(a: A, b: B, state: State<Meta>) => boolean,
|
|
301
|
+
) => (
|
|
302
|
+
a: any,
|
|
303
|
+
b: any,
|
|
304
|
+
indexOrKeyA: any,
|
|
305
|
+
indexOrKeyB: any,
|
|
306
|
+
parentA: any,
|
|
307
|
+
parentB: any,
|
|
308
|
+
state: State<Meta>,
|
|
309
|
+
) => boolean;
|
|
310
|
+
createState?: () => { cache?: Cache; meta?: Meta };
|
|
311
311
|
strict?: boolean;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function createCustomEqual(
|
|
315
|
-
options: CustomEqualCreatorOptions<Meta>,
|
|
316
|
-
): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
|
|
312
|
+
}): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
|
|
317
313
|
```
|
|
318
314
|
|
|
319
315
|
Create a custom equality comparator. This allows complete control over building a bespoke equality method, in case your use-case requires a higher degree of performance, legacy environment support, or any other non-standard usage. The [recipes](#recipes) provide examples of use in different use-cases, but if you have a specific goal in mind and would like assistance feel free to [file an issue](https://github.com/planttheidea/fast-equals/issues).
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
4
4
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
5
|
-
var SUPPORTS_ARRAY_BUFFER = typeof ArrayBuffer === 'function' && Boolean(ArrayBuffer.isView);
|
|
6
5
|
/**
|
|
7
6
|
* Combine two comparators into a single comparators.
|
|
8
7
|
*/
|
|
@@ -11,15 +10,6 @@ function combineComparators(comparatorA, comparatorB) {
|
|
|
11
10
|
return comparatorA(a, b, state) && comparatorB(a, b, state);
|
|
12
11
|
};
|
|
13
12
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Default equality comparator pass-through, used as the standard `isEqual` creator for
|
|
16
|
-
* use inside the built comparator.
|
|
17
|
-
*/
|
|
18
|
-
function createInternalComparator(compare) {
|
|
19
|
-
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
|
|
20
|
-
return compare(a, b, state);
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
13
|
/**
|
|
24
14
|
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
|
|
25
15
|
* for circular references to be safely included in the comparison without creating
|
|
@@ -58,9 +48,6 @@ var hasOwn = Object.hasOwn ||
|
|
|
58
48
|
(function (object, property) {
|
|
59
49
|
return hasOwnProperty.call(object, property);
|
|
60
50
|
});
|
|
61
|
-
function isArrayBuffer(value) {
|
|
62
|
-
return SUPPORTS_ARRAY_BUFFER && ArrayBuffer.isView(value);
|
|
63
|
-
}
|
|
64
51
|
/**
|
|
65
52
|
* Whether the values passed are strictly equal or both NaN.
|
|
66
53
|
*/
|
|
@@ -95,36 +82,42 @@ function areDatesEqual(a, b) {
|
|
|
95
82
|
* Whether the `Map`s are equal in value.
|
|
96
83
|
*/
|
|
97
84
|
function areMapsEqual(a, b, state) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
85
|
+
if (a.size !== b.size) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
var matchedIndices = {};
|
|
89
|
+
var aIterable = a.entries();
|
|
90
|
+
var index = 0;
|
|
91
|
+
var aResult;
|
|
92
|
+
var bResult;
|
|
93
|
+
while ((aResult = aIterable.next())) {
|
|
94
|
+
if (aResult.done) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
var bIterable = b.entries();
|
|
98
|
+
var hasMatch = false;
|
|
99
|
+
var matchIndex = 0;
|
|
100
|
+
while ((bResult = bIterable.next())) {
|
|
101
|
+
if (bResult.done) {
|
|
102
|
+
break;
|
|
110
103
|
}
|
|
111
|
-
var
|
|
112
|
-
var
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
(
|
|
117
|
-
state.equals(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
104
|
+
var _a = aResult.value, aKey = _a[0], aValue = _a[1];
|
|
105
|
+
var _b = bResult.value, bKey = _b[0], bValue = _b[1];
|
|
106
|
+
if (!hasMatch &&
|
|
107
|
+
!matchedIndices[matchIndex] &&
|
|
108
|
+
(hasMatch =
|
|
109
|
+
state.equals(aKey, bKey, index, matchIndex, a, b, state) &&
|
|
110
|
+
state.equals(aValue, bValue, aKey, bKey, a, b, state))) {
|
|
111
|
+
matchedIndices[matchIndex] = true;
|
|
112
|
+
}
|
|
113
|
+
matchIndex++;
|
|
114
|
+
}
|
|
115
|
+
if (!hasMatch) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
index++;
|
|
126
119
|
}
|
|
127
|
-
return
|
|
120
|
+
return true;
|
|
128
121
|
}
|
|
129
122
|
/**
|
|
130
123
|
* Whether the objects are equal in value.
|
|
@@ -212,33 +205,40 @@ function areRegExpsEqual(a, b) {
|
|
|
212
205
|
* Whether the `Set`s are equal in value.
|
|
213
206
|
*/
|
|
214
207
|
function areSetsEqual(a, b, state) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
208
|
+
if (a.size !== b.size) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
var matchedIndices = {};
|
|
212
|
+
var aIterable = a.values();
|
|
213
|
+
var aResult;
|
|
214
|
+
var bResult;
|
|
215
|
+
while ((aResult = aIterable.next())) {
|
|
216
|
+
if (aResult.done) {
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
var bIterable = b.values();
|
|
220
|
+
var hasMatch = false;
|
|
221
|
+
var matchIndex = 0;
|
|
222
|
+
while ((bResult = bIterable.next())) {
|
|
223
|
+
if (bResult.done) {
|
|
224
|
+
break;
|
|
226
225
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
isValueEqual = hasMatch;
|
|
238
|
-
});
|
|
226
|
+
if (!hasMatch &&
|
|
227
|
+
!matchedIndices[matchIndex] &&
|
|
228
|
+
(hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) {
|
|
229
|
+
matchedIndices[matchIndex] = true;
|
|
230
|
+
}
|
|
231
|
+
matchIndex++;
|
|
232
|
+
}
|
|
233
|
+
if (!hasMatch) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
239
236
|
}
|
|
240
|
-
return
|
|
237
|
+
return true;
|
|
241
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Whether the TypedArray instances are equal in value.
|
|
241
|
+
*/
|
|
242
242
|
function areTypedArraysEqual(a, b) {
|
|
243
243
|
var index = a.length;
|
|
244
244
|
if (b.length !== index) {
|
|
@@ -262,12 +262,15 @@ var REG_EXP_TAG = '[object RegExp]';
|
|
|
262
262
|
var SET_TAG = '[object Set]';
|
|
263
263
|
var STRING_TAG = '[object String]';
|
|
264
264
|
var isArray = Array.isArray;
|
|
265
|
+
var isTypedArray = typeof ArrayBuffer === 'function' && ArrayBuffer.isView
|
|
266
|
+
? ArrayBuffer.isView
|
|
267
|
+
: null;
|
|
265
268
|
var assign = Object.assign;
|
|
266
269
|
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
|
|
267
270
|
/**
|
|
268
271
|
* Create a comparator method based on the type-specific equality comparators passed.
|
|
269
272
|
*/
|
|
270
|
-
function
|
|
273
|
+
function createEqualityComparator(_a) {
|
|
271
274
|
var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areMapsEqual = _a.areMapsEqual, areObjectsEqual = _a.areObjectsEqual, arePrimitiveWrappersEqual = _a.arePrimitiveWrappersEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual, areTypedArraysEqual = _a.areTypedArraysEqual;
|
|
272
275
|
/**
|
|
273
276
|
* compare the value of the two objects and return true if they are equivalent in values
|
|
@@ -281,9 +284,13 @@ function createComparator(_a) {
|
|
|
281
284
|
// of them being equal but not strictly is if they are both `NaN`. Since
|
|
282
285
|
// `NaN` is uniquely not equal to itself, we can use self-comparison of
|
|
283
286
|
// both objects, which is faster than `isNaN()`.
|
|
284
|
-
if (
|
|
287
|
+
if (a == null ||
|
|
288
|
+
b == null ||
|
|
289
|
+
typeof a !== 'object' ||
|
|
290
|
+
typeof b !== 'object') {
|
|
285
291
|
return a !== a && b !== b;
|
|
286
292
|
}
|
|
293
|
+
var constructor = a.constructor;
|
|
287
294
|
// Checks are listed in order of commonality of use-case:
|
|
288
295
|
// 1. Common complex object types (plain object, array)
|
|
289
296
|
// 2. Common data values (date, regexp)
|
|
@@ -292,39 +299,47 @@ function createComparator(_a) {
|
|
|
292
299
|
// Inherently this is both subjective and assumptive, however
|
|
293
300
|
// when reviewing comparable libraries in the wild this order
|
|
294
301
|
// appears to be generally consistent.
|
|
302
|
+
// Constructors should match, otherwise there is potential for false positives
|
|
303
|
+
// between class and subclass or custom object and POJO.
|
|
304
|
+
if (constructor !== b.constructor) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
295
307
|
// `isPlainObject` only checks against the object's own realm. Cross-realm
|
|
296
308
|
// comparisons are rare, and will be handled in the ultimate fallback, so
|
|
297
|
-
// we can avoid the
|
|
298
|
-
if (
|
|
309
|
+
// we can avoid capturing the string tag.
|
|
310
|
+
if (constructor === Object) {
|
|
299
311
|
return areObjectsEqual(a, b, state);
|
|
300
312
|
}
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return false;
|
|
313
|
+
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
|
|
314
|
+
// the string tag or doing an `instanceof` check.
|
|
315
|
+
if (isArray(a)) {
|
|
316
|
+
return areArraysEqual(a, b, state);
|
|
306
317
|
}
|
|
307
|
-
// `
|
|
308
|
-
// the
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
return
|
|
319
|
-
}
|
|
320
|
-
// Since this is a custom object, use the classic `toString.call()` to get its
|
|
321
|
-
// type. This is reasonably performant in modern environments like v8 and
|
|
322
|
-
// SpiderMonkey, and allows for cross-realm comparison when other checks like
|
|
323
|
-
// `instanceof` do not.
|
|
324
|
-
var tag = getTag(a);
|
|
325
|
-
if (tag !== getTag(b)) {
|
|
326
|
-
return false;
|
|
318
|
+
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
|
|
319
|
+
// capturing the string tag or comparing against all possible constructors.
|
|
320
|
+
if (isTypedArray != null && isTypedArray(a)) {
|
|
321
|
+
return areTypedArraysEqual(a, b, state);
|
|
322
|
+
}
|
|
323
|
+
// Try to fast-path equality checks for other complex object types in the
|
|
324
|
+
// same realm to avoid capturing the string tag. Strict equality is used
|
|
325
|
+
// instead of `instanceof` because it is more performant for the common
|
|
326
|
+
// use-case. If someone is subclassing a native class, it will be handled
|
|
327
|
+
// with the string tag comparison.
|
|
328
|
+
if (constructor === Date) {
|
|
329
|
+
return areDatesEqual(a, b, state);
|
|
327
330
|
}
|
|
331
|
+
if (constructor === RegExp) {
|
|
332
|
+
return areRegExpsEqual(a, b, state);
|
|
333
|
+
}
|
|
334
|
+
if (constructor === Map) {
|
|
335
|
+
return areMapsEqual(a, b, state);
|
|
336
|
+
}
|
|
337
|
+
if (constructor === Set) {
|
|
338
|
+
return areSetsEqual(a, b, state);
|
|
339
|
+
}
|
|
340
|
+
// Since this is a custom object, capture the string tag to determing its type.
|
|
341
|
+
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
|
|
342
|
+
var tag = getTag(a);
|
|
328
343
|
if (tag === DATE_TAG) {
|
|
329
344
|
return areDatesEqual(a, b, state);
|
|
330
345
|
}
|
|
@@ -337,11 +352,9 @@ function createComparator(_a) {
|
|
|
337
352
|
if (tag === SET_TAG) {
|
|
338
353
|
return areSetsEqual(a, b, state);
|
|
339
354
|
}
|
|
340
|
-
// If a simple object tag, then we can prioritize a simple object comparison because
|
|
341
|
-
// it is likely a custom class.
|
|
342
355
|
if (tag === OBJECT_TAG) {
|
|
343
|
-
// The exception for value comparison is `Promise`-like
|
|
344
|
-
// treated the same as standard `Promise` objects, which means strict equality, and if
|
|
356
|
+
// The exception for value comparison is custom `Promise`-like class instances. These should
|
|
357
|
+
// be treated the same as standard `Promise` objects, which means strict equality, and if
|
|
345
358
|
// it reaches this point then that strict equality comparison has already failed.
|
|
346
359
|
return (typeof a.then !== 'function' &&
|
|
347
360
|
typeof b.then !== 'function' &&
|
|
@@ -374,7 +387,7 @@ function createComparator(_a) {
|
|
|
374
387
|
/**
|
|
375
388
|
* Create the configuration object used for building comparators.
|
|
376
389
|
*/
|
|
377
|
-
function
|
|
390
|
+
function createEqualityComparatorConfig(_a) {
|
|
378
391
|
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
|
|
379
392
|
var config = {
|
|
380
393
|
areArraysEqual: strict
|
|
@@ -393,7 +406,7 @@ function createComparatorConfig(_a) {
|
|
|
393
406
|
? combineComparators(areSetsEqual, areObjectsEqualStrict)
|
|
394
407
|
: areSetsEqual,
|
|
395
408
|
areTypedArraysEqual: strict
|
|
396
|
-
?
|
|
409
|
+
? areObjectsEqualStrict
|
|
397
410
|
: areTypedArraysEqual,
|
|
398
411
|
};
|
|
399
412
|
if (createCustomConfig) {
|
|
@@ -413,6 +426,51 @@ function createComparatorConfig(_a) {
|
|
|
413
426
|
}
|
|
414
427
|
return config;
|
|
415
428
|
}
|
|
429
|
+
/**
|
|
430
|
+
* Default equality comparator pass-through, used as the standard `isEqual` creator for
|
|
431
|
+
* use inside the built comparator.
|
|
432
|
+
*/
|
|
433
|
+
function createInternalEqualityComparator(compare) {
|
|
434
|
+
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
|
|
435
|
+
return compare(a, b, state);
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Create the `isEqual` function used by the consuming application.
|
|
440
|
+
*/
|
|
441
|
+
function createIsEqual(_a) {
|
|
442
|
+
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
|
|
443
|
+
if (createState) {
|
|
444
|
+
return function isEqual(a, b) {
|
|
445
|
+
var _a = createState(), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, meta = _a.meta;
|
|
446
|
+
return comparator(a, b, {
|
|
447
|
+
cache: cache,
|
|
448
|
+
equals: equals,
|
|
449
|
+
meta: meta,
|
|
450
|
+
strict: strict,
|
|
451
|
+
});
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
if (circular) {
|
|
455
|
+
return function isEqual(a, b) {
|
|
456
|
+
return comparator(a, b, {
|
|
457
|
+
cache: new WeakMap(),
|
|
458
|
+
equals: equals,
|
|
459
|
+
meta: undefined,
|
|
460
|
+
strict: strict,
|
|
461
|
+
});
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
var state = {
|
|
465
|
+
cache: undefined,
|
|
466
|
+
equals: equals,
|
|
467
|
+
meta: undefined,
|
|
468
|
+
strict: strict,
|
|
469
|
+
};
|
|
470
|
+
return function isEqual(a, b) {
|
|
471
|
+
return comparator(a, b, state);
|
|
472
|
+
};
|
|
473
|
+
}
|
|
416
474
|
|
|
417
475
|
/**
|
|
418
476
|
* Whether the items passed are deeply-equal in value.
|
|
@@ -438,29 +496,29 @@ var strictCircularDeepEqual = createCustomEqual({
|
|
|
438
496
|
* Whether the items passed are shallowly-equal in value.
|
|
439
497
|
*/
|
|
440
498
|
var shallowEqual = createCustomEqual({
|
|
441
|
-
|
|
499
|
+
createInternalComparator: function () { return sameValueZeroEqual; },
|
|
442
500
|
});
|
|
443
501
|
/**
|
|
444
502
|
* Whether the items passed are shallowly-equal in value based on strict comparison
|
|
445
503
|
*/
|
|
446
504
|
var strictShallowEqual = createCustomEqual({
|
|
447
|
-
comparator: sameValueZeroEqual,
|
|
448
505
|
strict: true,
|
|
506
|
+
createInternalComparator: function () { return sameValueZeroEqual; },
|
|
449
507
|
});
|
|
450
508
|
/**
|
|
451
509
|
* Whether the items passed are shallowly-equal in value, including circular references.
|
|
452
510
|
*/
|
|
453
511
|
var circularShallowEqual = createCustomEqual({
|
|
454
|
-
comparator: sameValueZeroEqual,
|
|
455
512
|
circular: true,
|
|
513
|
+
createInternalComparator: function () { return sameValueZeroEqual; },
|
|
456
514
|
});
|
|
457
515
|
/**
|
|
458
516
|
* Whether the items passed are shallowly-equal in value, including circular references,
|
|
459
517
|
* based on strict comparison.
|
|
460
518
|
*/
|
|
461
519
|
var strictCircularShallowEqual = createCustomEqual({
|
|
462
|
-
comparator: sameValueZeroEqual,
|
|
463
520
|
circular: true,
|
|
521
|
+
createInternalComparator: function () { return sameValueZeroEqual; },
|
|
464
522
|
strict: true,
|
|
465
523
|
});
|
|
466
524
|
/**
|
|
@@ -473,43 +531,13 @@ var strictCircularShallowEqual = createCustomEqual({
|
|
|
473
531
|
*/
|
|
474
532
|
function createCustomEqual(options) {
|
|
475
533
|
if (options === void 0) { options = {}; }
|
|
476
|
-
var
|
|
477
|
-
var config =
|
|
478
|
-
var
|
|
479
|
-
var
|
|
480
|
-
(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (createState) {
|
|
484
|
-
return function isEqual(a, b, metaOverride) {
|
|
485
|
-
var _a = createState(isEqualCustom), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, _c = _a.equals, equals = _c === void 0 ? isEqualCustomComparator : _c, meta = _a.meta, _d = _a.strict, strict = _d === void 0 ? baseStrict : _d;
|
|
486
|
-
return isEqualCustom(a, b, {
|
|
487
|
-
cache: cache,
|
|
488
|
-
equals: equals,
|
|
489
|
-
meta: metaOverride !== undefined ? metaOverride : meta,
|
|
490
|
-
strict: strict,
|
|
491
|
-
});
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
if (circular) {
|
|
495
|
-
return function equals(a, b) {
|
|
496
|
-
return isEqualCustom(a, b, {
|
|
497
|
-
cache: new WeakMap(),
|
|
498
|
-
equals: isEqualCustomComparator,
|
|
499
|
-
meta: undefined,
|
|
500
|
-
strict: baseStrict,
|
|
501
|
-
});
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
var state = Object.freeze({
|
|
505
|
-
cache: undefined,
|
|
506
|
-
equals: isEqualCustomComparator,
|
|
507
|
-
meta: undefined,
|
|
508
|
-
strict: baseStrict,
|
|
509
|
-
});
|
|
510
|
-
return function equals(a, b) {
|
|
511
|
-
return isEqualCustom(a, b, state);
|
|
512
|
-
};
|
|
534
|
+
var _a = options.circular, circular = _a === void 0 ? false : _a, createCustomInternalComparator = options.createInternalComparator, createState = options.createState, _b = options.strict, strict = _b === void 0 ? false : _b;
|
|
535
|
+
var config = createEqualityComparatorConfig(options);
|
|
536
|
+
var comparator = createEqualityComparator(config);
|
|
537
|
+
var equals = createCustomInternalComparator
|
|
538
|
+
? createCustomInternalComparator(comparator)
|
|
539
|
+
: createInternalEqualityComparator(comparator);
|
|
540
|
+
return createIsEqual({ circular: circular, comparator: comparator, createState: createState, equals: equals, strict: strict });
|
|
513
541
|
}
|
|
514
542
|
|
|
515
543
|
exports.circularDeepEqual = circularDeepEqual;
|