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