fast-equals 5.3.3 → 5.4.0
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/LICENSE +1 -1
- package/README.md +128 -77
- package/dist/cjs/comparator.d.cts +60 -0
- package/dist/cjs/{types/equals.d.cts → equals.d.cts} +8 -0
- package/dist/cjs/index.cjs +171 -162
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/{types/index.d.cts → index.d.cts} +21 -2
- package/{src/internalTypes.ts → dist/cjs/internalTypes.d.cts} +18 -50
- package/dist/cjs/{types/utils.d.cts → utils.d.cts} +7 -2
- package/dist/es/comparator.d.mts +60 -0
- package/dist/{esm/types → es}/equals.d.mts +8 -0
- package/dist/{esm/types → es}/index.d.mts +21 -2
- package/dist/{esm → es}/index.mjs +171 -162
- package/dist/es/index.mjs.map +1 -0
- package/dist/es/internalTypes.d.mts +178 -0
- package/dist/{esm/types → es}/utils.d.mts +7 -2
- package/dist/{min/types → umd}/comparator.d.ts +2 -2
- package/dist/{min/types → umd}/equals.d.ts +8 -0
- package/dist/umd/index.js +171 -162
- package/dist/umd/index.js.map +1 -1
- package/dist/{min/types → umd}/internalTypes.d.ts +10 -8
- package/index.d.ts +73 -75
- package/package.json +45 -48
- package/CHANGELOG.md +0 -364
- package/dist/cjs/types/comparator.d.cts +0 -26
- package/dist/cjs/types/internalTypes.d.cts +0 -157
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/types/comparator.d.mts +0 -26
- package/dist/esm/types/internalTypes.d.mts +0 -157
- package/dist/min/index.js +0 -1
- package/dist/umd/types/comparator.d.ts +0 -26
- package/dist/umd/types/equals.d.ts +0 -54
- package/dist/umd/types/index.d.ts +0 -47
- package/dist/umd/types/internalTypes.d.ts +0 -157
- package/dist/umd/types/utils.d.ts +0 -28
- package/src/comparator.ts +0 -376
- package/src/equals.ts +0 -355
- package/src/index.ts +0 -112
- package/src/utils.ts +0 -96
- /package/dist/{min/types → umd}/index.d.ts +0 -0
- /package/dist/{min/types → umd}/utils.d.ts +0 -0
package/dist/umd/index.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["fast-equals"] = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
9
|
+
const { hasOwnProperty } = Object.prototype;
|
|
9
10
|
/**
|
|
10
11
|
* Combine two comparators into a single comparators.
|
|
11
12
|
*/
|
|
@@ -24,15 +25,15 @@
|
|
|
24
25
|
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
|
|
25
26
|
return areItemsEqual(a, b, state);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const { cache } = state;
|
|
29
|
+
const cachedA = cache.get(a);
|
|
30
|
+
const cachedB = cache.get(b);
|
|
30
31
|
if (cachedA && cachedB) {
|
|
31
32
|
return cachedA === b && cachedB === a;
|
|
32
33
|
}
|
|
33
34
|
cache.set(a, b);
|
|
34
35
|
cache.set(b, a);
|
|
35
|
-
|
|
36
|
+
const result = areItemsEqual(a, b, state);
|
|
36
37
|
cache.delete(a);
|
|
37
38
|
cache.delete(b);
|
|
38
39
|
return result;
|
|
@@ -54,12 +55,9 @@
|
|
|
54
55
|
/**
|
|
55
56
|
* Whether the object contains the property passed as an own property.
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
+
const hasOwn =
|
|
58
59
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
59
|
-
Object.hasOwn ||
|
|
60
|
-
(function (object, property) {
|
|
61
|
-
return hasOwnProperty.call(object, property);
|
|
62
|
-
});
|
|
60
|
+
Object.hasOwn || ((object, property) => hasOwnProperty.call(object, property));
|
|
63
61
|
/**
|
|
64
62
|
* Whether the values passed are strictly equal or both NaN.
|
|
65
63
|
*/
|
|
@@ -67,15 +65,21 @@
|
|
|
67
65
|
return a === b || (!a && !b && a !== a && b !== b);
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
const PREACT_VNODE = '__v';
|
|
69
|
+
const PREACT_OWNER = '__o';
|
|
70
|
+
const REACT_OWNER = '_owner';
|
|
71
|
+
const { getOwnPropertyDescriptor, keys } = Object;
|
|
72
|
+
/**
|
|
73
|
+
* Whether the array buffers are equal in value.
|
|
74
|
+
*/
|
|
75
|
+
function areArrayBuffersEqual(a, b) {
|
|
76
|
+
return a.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a), new Uint8Array(b));
|
|
77
|
+
}
|
|
74
78
|
/**
|
|
75
79
|
* Whether the arrays are equal in value.
|
|
76
80
|
*/
|
|
77
81
|
function areArraysEqual(a, b, state) {
|
|
78
|
-
|
|
82
|
+
let index = a.length;
|
|
79
83
|
if (b.length !== index) {
|
|
80
84
|
return false;
|
|
81
85
|
}
|
|
@@ -86,6 +90,13 @@
|
|
|
86
90
|
}
|
|
87
91
|
return true;
|
|
88
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Whether the dataviews are equal in value.
|
|
95
|
+
*/
|
|
96
|
+
function areDataViewsEqual(a, b) {
|
|
97
|
+
return (a.byteLength === b.byteLength
|
|
98
|
+
&& areTypedArraysEqual(new Uint8Array(a.buffer, a.byteOffset, a.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength)));
|
|
99
|
+
}
|
|
89
100
|
/**
|
|
90
101
|
* Whether the dates passed are equal in value.
|
|
91
102
|
*/
|
|
@@ -96,10 +107,7 @@
|
|
|
96
107
|
* Whether the errors passed are equal in value.
|
|
97
108
|
*/
|
|
98
109
|
function areErrorsEqual(a, b) {
|
|
99
|
-
return
|
|
100
|
-
a.message === b.message &&
|
|
101
|
-
a.cause === b.cause &&
|
|
102
|
-
a.stack === b.stack);
|
|
110
|
+
return a.name === b.name && a.message === b.message && a.cause === b.cause && a.stack === b.stack;
|
|
103
111
|
}
|
|
104
112
|
/**
|
|
105
113
|
* Whether the functions passed are equal in value.
|
|
@@ -111,26 +119,26 @@
|
|
|
111
119
|
* Whether the `Map`s are equal in value.
|
|
112
120
|
*/
|
|
113
121
|
function areMapsEqual(a, b, state) {
|
|
114
|
-
|
|
122
|
+
const size = a.size;
|
|
115
123
|
if (size !== b.size) {
|
|
116
124
|
return false;
|
|
117
125
|
}
|
|
118
126
|
if (!size) {
|
|
119
127
|
return true;
|
|
120
128
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
const matchedIndices = new Array(size);
|
|
130
|
+
const aIterable = a.entries();
|
|
131
|
+
let aResult;
|
|
132
|
+
let bResult;
|
|
133
|
+
let index = 0;
|
|
126
134
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
127
135
|
while ((aResult = aIterable.next())) {
|
|
128
136
|
if (aResult.done) {
|
|
129
137
|
break;
|
|
130
138
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
const bIterable = b.entries();
|
|
140
|
+
let hasMatch = false;
|
|
141
|
+
let matchIndex = 0;
|
|
134
142
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
135
143
|
while ((bResult = bIterable.next())) {
|
|
136
144
|
if (bResult.done) {
|
|
@@ -140,10 +148,10 @@
|
|
|
140
148
|
matchIndex++;
|
|
141
149
|
continue;
|
|
142
150
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state)
|
|
146
|
-
state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
|
|
151
|
+
const aEntry = aResult.value;
|
|
152
|
+
const bEntry = bResult.value;
|
|
153
|
+
if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state)
|
|
154
|
+
&& state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
|
|
147
155
|
hasMatch = matchedIndices[matchIndex] = true;
|
|
148
156
|
break;
|
|
149
157
|
}
|
|
@@ -159,13 +167,13 @@
|
|
|
159
167
|
/**
|
|
160
168
|
* Whether the numbers are equal in value.
|
|
161
169
|
*/
|
|
162
|
-
|
|
170
|
+
const areNumbersEqual = sameValueZeroEqual;
|
|
163
171
|
/**
|
|
164
172
|
* Whether the objects are equal in value.
|
|
165
173
|
*/
|
|
166
174
|
function areObjectsEqual(a, b, state) {
|
|
167
|
-
|
|
168
|
-
|
|
175
|
+
const properties = keys(a);
|
|
176
|
+
let index = properties.length;
|
|
169
177
|
if (keys(b).length !== index) {
|
|
170
178
|
return false;
|
|
171
179
|
}
|
|
@@ -184,14 +192,14 @@
|
|
|
184
192
|
* Whether the objects are equal in value with strict property checking.
|
|
185
193
|
*/
|
|
186
194
|
function areObjectsEqualStrict(a, b, state) {
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
const properties = getStrictProperties(a);
|
|
196
|
+
let index = properties.length;
|
|
189
197
|
if (getStrictProperties(b).length !== index) {
|
|
190
198
|
return false;
|
|
191
199
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
200
|
+
let property;
|
|
201
|
+
let descriptorA;
|
|
202
|
+
let descriptorB;
|
|
195
203
|
// Decrementing `while` showed faster results than either incrementing or
|
|
196
204
|
// decrementing `for` loop and than an incrementing `while` loop. Declarative
|
|
197
205
|
// methods like `some` / `every` were not used to avoid incurring the garbage
|
|
@@ -203,12 +211,12 @@
|
|
|
203
211
|
}
|
|
204
212
|
descriptorA = getOwnPropertyDescriptor(a, property);
|
|
205
213
|
descriptorB = getOwnPropertyDescriptor(b, property);
|
|
206
|
-
if ((descriptorA || descriptorB)
|
|
207
|
-
(!descriptorA
|
|
208
|
-
!descriptorB
|
|
209
|
-
descriptorA.configurable !== descriptorB.configurable
|
|
210
|
-
descriptorA.enumerable !== descriptorB.enumerable
|
|
211
|
-
descriptorA.writable !== descriptorB.writable)) {
|
|
214
|
+
if ((descriptorA || descriptorB)
|
|
215
|
+
&& (!descriptorA
|
|
216
|
+
|| !descriptorB
|
|
217
|
+
|| descriptorA.configurable !== descriptorB.configurable
|
|
218
|
+
|| descriptorA.enumerable !== descriptorB.enumerable
|
|
219
|
+
|| descriptorA.writable !== descriptorB.writable)) {
|
|
212
220
|
return false;
|
|
213
221
|
}
|
|
214
222
|
}
|
|
@@ -230,32 +238,32 @@
|
|
|
230
238
|
* Whether the `Set`s are equal in value.
|
|
231
239
|
*/
|
|
232
240
|
function areSetsEqual(a, b, state) {
|
|
233
|
-
|
|
241
|
+
const size = a.size;
|
|
234
242
|
if (size !== b.size) {
|
|
235
243
|
return false;
|
|
236
244
|
}
|
|
237
245
|
if (!size) {
|
|
238
246
|
return true;
|
|
239
247
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
const matchedIndices = new Array(size);
|
|
249
|
+
const aIterable = a.values();
|
|
250
|
+
let aResult;
|
|
251
|
+
let bResult;
|
|
244
252
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
245
253
|
while ((aResult = aIterable.next())) {
|
|
246
254
|
if (aResult.done) {
|
|
247
255
|
break;
|
|
248
256
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
const bIterable = b.values();
|
|
258
|
+
let hasMatch = false;
|
|
259
|
+
let matchIndex = 0;
|
|
252
260
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
253
261
|
while ((bResult = bIterable.next())) {
|
|
254
262
|
if (bResult.done) {
|
|
255
263
|
break;
|
|
256
264
|
}
|
|
257
|
-
if (!matchedIndices[matchIndex]
|
|
258
|
-
state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
|
|
265
|
+
if (!matchedIndices[matchIndex]
|
|
266
|
+
&& state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
|
|
259
267
|
hasMatch = matchedIndices[matchIndex] = true;
|
|
260
268
|
break;
|
|
261
269
|
}
|
|
@@ -271,8 +279,8 @@
|
|
|
271
279
|
* Whether the TypedArray instances are equal in value.
|
|
272
280
|
*/
|
|
273
281
|
function areTypedArraysEqual(a, b) {
|
|
274
|
-
|
|
275
|
-
if (b.
|
|
282
|
+
let index = a.byteLength;
|
|
283
|
+
if (b.byteLength !== index || a.byteOffset !== b.byteOffset) {
|
|
276
284
|
return false;
|
|
277
285
|
}
|
|
278
286
|
while (index-- > 0) {
|
|
@@ -286,47 +294,55 @@
|
|
|
286
294
|
* Whether the URL instances are equal in value.
|
|
287
295
|
*/
|
|
288
296
|
function areUrlsEqual(a, b) {
|
|
289
|
-
return (a.hostname === b.hostname
|
|
290
|
-
a.pathname === b.pathname
|
|
291
|
-
a.protocol === b.protocol
|
|
292
|
-
a.port === b.port
|
|
293
|
-
a.hash === b.hash
|
|
294
|
-
a.username === b.username
|
|
295
|
-
a.password === b.password);
|
|
297
|
+
return (a.hostname === b.hostname
|
|
298
|
+
&& a.pathname === b.pathname
|
|
299
|
+
&& a.protocol === b.protocol
|
|
300
|
+
&& a.port === b.port
|
|
301
|
+
&& a.hash === b.hash
|
|
302
|
+
&& a.username === b.username
|
|
303
|
+
&& a.password === b.password);
|
|
296
304
|
}
|
|
297
305
|
function isPropertyEqual(a, b, state, property) {
|
|
298
|
-
if ((property === REACT_OWNER ||
|
|
299
|
-
|
|
300
|
-
property === PREACT_VNODE) &&
|
|
301
|
-
(a.$$typeof || b.$$typeof)) {
|
|
306
|
+
if ((property === REACT_OWNER || property === PREACT_OWNER || property === PREACT_VNODE)
|
|
307
|
+
&& (a.$$typeof || b.$$typeof)) {
|
|
302
308
|
return true;
|
|
303
309
|
}
|
|
304
|
-
return
|
|
305
|
-
state.equals(a[property], b[property], property, property, a, b, state));
|
|
310
|
+
return hasOwn(b, property) && state.equals(a[property], b[property], property, property, a, b, state);
|
|
306
311
|
}
|
|
307
312
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
:
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
const ARRAY_BUFFER_TAG = '[object ArrayBuffer]';
|
|
314
|
+
const ARGUMENTS_TAG = '[object Arguments]';
|
|
315
|
+
const BOOLEAN_TAG = '[object Boolean]';
|
|
316
|
+
const DATA_VIEW_TAG = '[object DataView]';
|
|
317
|
+
const DATE_TAG = '[object Date]';
|
|
318
|
+
const ERROR_TAG = '[object Error]';
|
|
319
|
+
const MAP_TAG = '[object Map]';
|
|
320
|
+
const NUMBER_TAG = '[object Number]';
|
|
321
|
+
const OBJECT_TAG = '[object Object]';
|
|
322
|
+
const REG_EXP_TAG = '[object RegExp]';
|
|
323
|
+
const SET_TAG = '[object Set]';
|
|
324
|
+
const STRING_TAG = '[object String]';
|
|
325
|
+
const TYPED_ARRAY_TAGS = {
|
|
326
|
+
'[object Int8Array]': true,
|
|
327
|
+
'[object Uint8Array]': true,
|
|
328
|
+
'[object Uint8ClampedArray]': true,
|
|
329
|
+
'[object Int16Array]': true,
|
|
330
|
+
'[object Uint16Array]': true,
|
|
331
|
+
'[object Int32Array]': true,
|
|
332
|
+
'[object Uint32Array]': true,
|
|
333
|
+
'[object Float16Array]': true,
|
|
334
|
+
'[object Float32Array]': true,
|
|
335
|
+
'[object Float64Array]': true,
|
|
336
|
+
'[object BigInt64Array]': true,
|
|
337
|
+
'[object BigUint64Array]': true,
|
|
338
|
+
};
|
|
339
|
+
const URL_TAG = '[object URL]';
|
|
340
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
341
|
+
const toString = Object.prototype.toString;
|
|
325
342
|
/**
|
|
326
343
|
* Create a comparator method based on the type-specific equality comparators passed.
|
|
327
344
|
*/
|
|
328
|
-
function createEqualityComparator(
|
|
329
|
-
var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areErrorsEqual = _a.areErrorsEqual, areFunctionsEqual = _a.areFunctionsEqual, areMapsEqual = _a.areMapsEqual, areNumbersEqual = _a.areNumbersEqual, areObjectsEqual = _a.areObjectsEqual, arePrimitiveWrappersEqual = _a.arePrimitiveWrappersEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual, areTypedArraysEqual = _a.areTypedArraysEqual, areUrlsEqual = _a.areUrlsEqual, unknownTagComparators = _a.unknownTagComparators;
|
|
345
|
+
function createEqualityComparator({ areArrayBuffersEqual, areArraysEqual, areDataViewsEqual, areDatesEqual, areErrorsEqual, areFunctionsEqual, areMapsEqual, areNumbersEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, areUrlsEqual, unknownTagComparators, }) {
|
|
330
346
|
/**
|
|
331
347
|
* compare the value of the two objects and return true if they are equivalent in values
|
|
332
348
|
*/
|
|
@@ -340,7 +356,7 @@
|
|
|
340
356
|
if (a == null || b == null) {
|
|
341
357
|
return false;
|
|
342
358
|
}
|
|
343
|
-
|
|
359
|
+
const type = typeof a;
|
|
344
360
|
if (type !== typeof b) {
|
|
345
361
|
return false;
|
|
346
362
|
}
|
|
@@ -354,7 +370,7 @@
|
|
|
354
370
|
// If a primitive value that is not strictly equal, it must be unequal.
|
|
355
371
|
return false;
|
|
356
372
|
}
|
|
357
|
-
|
|
373
|
+
const constructor = a.constructor;
|
|
358
374
|
// Checks are listed in order of commonality of use-case:
|
|
359
375
|
// 1. Common complex object types (plain object, array)
|
|
360
376
|
// 2. Common data values (date, regexp)
|
|
@@ -376,14 +392,9 @@
|
|
|
376
392
|
}
|
|
377
393
|
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
|
|
378
394
|
// the string tag or doing an `instanceof` check.
|
|
379
|
-
if (isArray(a)) {
|
|
395
|
+
if (Array.isArray(a)) {
|
|
380
396
|
return areArraysEqual(a, b, state);
|
|
381
397
|
}
|
|
382
|
-
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
|
|
383
|
-
// capturing the string tag or comparing against all possible constructors.
|
|
384
|
-
if (isTypedArray != null && isTypedArray(a)) {
|
|
385
|
-
return areTypedArraysEqual(a, b, state);
|
|
386
|
-
}
|
|
387
398
|
// Try to fast-path equality checks for other complex object types in the
|
|
388
399
|
// same realm to avoid capturing the string tag. Strict equality is used
|
|
389
400
|
// instead of `instanceof` because it is more performant for the common
|
|
@@ -403,7 +414,7 @@
|
|
|
403
414
|
}
|
|
404
415
|
// Since this is a custom object, capture the string tag to determing its type.
|
|
405
416
|
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
|
|
406
|
-
|
|
417
|
+
const tag = toString.call(a);
|
|
407
418
|
if (tag === DATE_TAG) {
|
|
408
419
|
return areDatesEqual(a, b, state);
|
|
409
420
|
}
|
|
@@ -422,9 +433,7 @@
|
|
|
422
433
|
// The exception for value comparison is custom `Promise`-like class instances. These should
|
|
423
434
|
// be treated the same as standard `Promise` objects, which means strict equality, and if
|
|
424
435
|
// it reaches this point then that strict equality comparison has already failed.
|
|
425
|
-
return
|
|
426
|
-
typeof b.then !== 'function' &&
|
|
427
|
-
areObjectsEqual(a, b, state));
|
|
436
|
+
return typeof a.then !== 'function' && typeof b.then !== 'function' && areObjectsEqual(a, b, state);
|
|
428
437
|
}
|
|
429
438
|
// If a URL tag, it should be tested explicitly. Like RegExp, the properties are not
|
|
430
439
|
// enumerable, and therefore will give false positives if tested like a standard object.
|
|
@@ -440,6 +449,15 @@
|
|
|
440
449
|
if (tag === ARGUMENTS_TAG) {
|
|
441
450
|
return areObjectsEqual(a, b, state);
|
|
442
451
|
}
|
|
452
|
+
if (TYPED_ARRAY_TAGS[tag]) {
|
|
453
|
+
return areTypedArraysEqual(a, b, state);
|
|
454
|
+
}
|
|
455
|
+
if (tag === ARRAY_BUFFER_TAG) {
|
|
456
|
+
return areArrayBuffersEqual(a, b, state);
|
|
457
|
+
}
|
|
458
|
+
if (tag === DATA_VIEW_TAG) {
|
|
459
|
+
return areDataViewsEqual(a, b, state);
|
|
460
|
+
}
|
|
443
461
|
// As the penultimate fallback, check if the values passed are primitive wrappers. This
|
|
444
462
|
// is very rare in modern JS, which is why it is deprioritized compared to all other object
|
|
445
463
|
// types.
|
|
@@ -447,9 +465,9 @@
|
|
|
447
465
|
return arePrimitiveWrappersEqual(a, b, state);
|
|
448
466
|
}
|
|
449
467
|
if (unknownTagComparators) {
|
|
450
|
-
|
|
468
|
+
let unknownTagComparator = unknownTagComparators[tag];
|
|
451
469
|
if (!unknownTagComparator) {
|
|
452
|
-
|
|
470
|
+
const shortTag = getShortTag(a);
|
|
453
471
|
if (shortTag) {
|
|
454
472
|
unknownTagComparator = unknownTagComparators[shortTag];
|
|
455
473
|
}
|
|
@@ -477,46 +495,39 @@
|
|
|
477
495
|
/**
|
|
478
496
|
* Create the configuration object used for building comparators.
|
|
479
497
|
*/
|
|
480
|
-
function createEqualityComparatorConfig(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
areArraysEqual: strict
|
|
484
|
-
|
|
485
|
-
: areArraysEqual,
|
|
498
|
+
function createEqualityComparatorConfig({ circular, createCustomConfig, strict, }) {
|
|
499
|
+
let config = {
|
|
500
|
+
areArrayBuffersEqual,
|
|
501
|
+
areArraysEqual: strict ? areObjectsEqualStrict : areArraysEqual,
|
|
502
|
+
areDataViewsEqual,
|
|
486
503
|
areDatesEqual: areDatesEqual,
|
|
487
504
|
areErrorsEqual: areErrorsEqual,
|
|
488
505
|
areFunctionsEqual: areFunctionsEqual,
|
|
489
|
-
areMapsEqual: strict
|
|
490
|
-
? combineComparators(areMapsEqual, areObjectsEqualStrict)
|
|
491
|
-
: areMapsEqual,
|
|
506
|
+
areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
|
|
492
507
|
areNumbersEqual: areNumbersEqual,
|
|
493
|
-
areObjectsEqual: strict
|
|
494
|
-
? areObjectsEqualStrict
|
|
495
|
-
: areObjectsEqual,
|
|
508
|
+
areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
|
|
496
509
|
arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
|
|
497
510
|
areRegExpsEqual: areRegExpsEqual,
|
|
498
|
-
areSetsEqual: strict
|
|
499
|
-
? combineComparators(areSetsEqual, areObjectsEqualStrict)
|
|
500
|
-
: areSetsEqual,
|
|
511
|
+
areSetsEqual: strict ? combineComparators(areSetsEqual, areObjectsEqualStrict) : areSetsEqual,
|
|
501
512
|
areTypedArraysEqual: strict
|
|
502
|
-
? areObjectsEqualStrict
|
|
513
|
+
? combineComparators(areTypedArraysEqual, areObjectsEqualStrict)
|
|
503
514
|
: areTypedArraysEqual,
|
|
504
515
|
areUrlsEqual: areUrlsEqual,
|
|
505
516
|
unknownTagComparators: undefined,
|
|
506
517
|
};
|
|
507
518
|
if (createCustomConfig) {
|
|
508
|
-
config = assign({}, config, createCustomConfig(config));
|
|
519
|
+
config = Object.assign({}, config, createCustomConfig(config));
|
|
509
520
|
}
|
|
510
521
|
if (circular) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
config = assign({}, config, {
|
|
516
|
-
areArraysEqual
|
|
517
|
-
areMapsEqual
|
|
518
|
-
areObjectsEqual
|
|
519
|
-
areSetsEqual
|
|
522
|
+
const areArraysEqual = createIsCircular(config.areArraysEqual);
|
|
523
|
+
const areMapsEqual = createIsCircular(config.areMapsEqual);
|
|
524
|
+
const areObjectsEqual = createIsCircular(config.areObjectsEqual);
|
|
525
|
+
const areSetsEqual = createIsCircular(config.areSetsEqual);
|
|
526
|
+
config = Object.assign({}, config, {
|
|
527
|
+
areArraysEqual,
|
|
528
|
+
areMapsEqual,
|
|
529
|
+
areObjectsEqual,
|
|
530
|
+
areSetsEqual,
|
|
520
531
|
});
|
|
521
532
|
}
|
|
522
533
|
return config;
|
|
@@ -533,16 +544,15 @@
|
|
|
533
544
|
/**
|
|
534
545
|
* Create the `isEqual` function used by the consuming application.
|
|
535
546
|
*/
|
|
536
|
-
function createIsEqual(
|
|
537
|
-
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
|
|
547
|
+
function createIsEqual({ circular, comparator, createState, equals, strict }) {
|
|
538
548
|
if (createState) {
|
|
539
549
|
return function isEqual(a, b) {
|
|
540
|
-
|
|
550
|
+
const { cache = circular ? new WeakMap() : undefined, meta } = createState();
|
|
541
551
|
return comparator(a, b, {
|
|
542
|
-
cache
|
|
543
|
-
equals
|
|
544
|
-
meta
|
|
545
|
-
strict
|
|
552
|
+
cache,
|
|
553
|
+
equals,
|
|
554
|
+
meta,
|
|
555
|
+
strict,
|
|
546
556
|
});
|
|
547
557
|
};
|
|
548
558
|
}
|
|
@@ -550,17 +560,17 @@
|
|
|
550
560
|
return function isEqual(a, b) {
|
|
551
561
|
return comparator(a, b, {
|
|
552
562
|
cache: new WeakMap(),
|
|
553
|
-
equals
|
|
563
|
+
equals,
|
|
554
564
|
meta: undefined,
|
|
555
|
-
strict
|
|
565
|
+
strict,
|
|
556
566
|
});
|
|
557
567
|
};
|
|
558
568
|
}
|
|
559
|
-
|
|
569
|
+
const state = {
|
|
560
570
|
cache: undefined,
|
|
561
|
-
equals
|
|
571
|
+
equals,
|
|
562
572
|
meta: undefined,
|
|
563
|
-
strict
|
|
573
|
+
strict,
|
|
564
574
|
};
|
|
565
575
|
return function isEqual(a, b) {
|
|
566
576
|
return comparator(a, b, state);
|
|
@@ -570,50 +580,50 @@
|
|
|
570
580
|
/**
|
|
571
581
|
* Whether the items passed are deeply-equal in value.
|
|
572
582
|
*/
|
|
573
|
-
|
|
583
|
+
const deepEqual = createCustomEqual();
|
|
574
584
|
/**
|
|
575
585
|
* Whether the items passed are deeply-equal in value based on strict comparison.
|
|
576
586
|
*/
|
|
577
|
-
|
|
587
|
+
const strictDeepEqual = createCustomEqual({ strict: true });
|
|
578
588
|
/**
|
|
579
589
|
* Whether the items passed are deeply-equal in value, including circular references.
|
|
580
590
|
*/
|
|
581
|
-
|
|
591
|
+
const circularDeepEqual = createCustomEqual({ circular: true });
|
|
582
592
|
/**
|
|
583
593
|
* Whether the items passed are deeply-equal in value, including circular references,
|
|
584
594
|
* based on strict comparison.
|
|
585
595
|
*/
|
|
586
|
-
|
|
596
|
+
const strictCircularDeepEqual = createCustomEqual({
|
|
587
597
|
circular: true,
|
|
588
598
|
strict: true,
|
|
589
599
|
});
|
|
590
600
|
/**
|
|
591
601
|
* Whether the items passed are shallowly-equal in value.
|
|
592
602
|
*/
|
|
593
|
-
|
|
594
|
-
createInternalComparator:
|
|
603
|
+
const shallowEqual = createCustomEqual({
|
|
604
|
+
createInternalComparator: () => sameValueZeroEqual,
|
|
595
605
|
});
|
|
596
606
|
/**
|
|
597
607
|
* Whether the items passed are shallowly-equal in value based on strict comparison
|
|
598
608
|
*/
|
|
599
|
-
|
|
609
|
+
const strictShallowEqual = createCustomEqual({
|
|
600
610
|
strict: true,
|
|
601
|
-
createInternalComparator:
|
|
611
|
+
createInternalComparator: () => sameValueZeroEqual,
|
|
602
612
|
});
|
|
603
613
|
/**
|
|
604
614
|
* Whether the items passed are shallowly-equal in value, including circular references.
|
|
605
615
|
*/
|
|
606
|
-
|
|
616
|
+
const circularShallowEqual = createCustomEqual({
|
|
607
617
|
circular: true,
|
|
608
|
-
createInternalComparator:
|
|
618
|
+
createInternalComparator: () => sameValueZeroEqual,
|
|
609
619
|
});
|
|
610
620
|
/**
|
|
611
621
|
* Whether the items passed are shallowly-equal in value, including circular references,
|
|
612
622
|
* based on strict comparison.
|
|
613
623
|
*/
|
|
614
|
-
|
|
624
|
+
const strictCircularShallowEqual = createCustomEqual({
|
|
615
625
|
circular: true,
|
|
616
|
-
createInternalComparator:
|
|
626
|
+
createInternalComparator: () => sameValueZeroEqual,
|
|
617
627
|
strict: true,
|
|
618
628
|
});
|
|
619
629
|
/**
|
|
@@ -624,15 +634,14 @@
|
|
|
624
634
|
* support for legacy environments that do not support expected features like
|
|
625
635
|
* `RegExp.prototype.flags` out of the box.
|
|
626
636
|
*/
|
|
627
|
-
function createCustomEqual(options) {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
var equals = createCustomInternalComparator
|
|
637
|
+
function createCustomEqual(options = {}) {
|
|
638
|
+
const { circular = false, createInternalComparator: createCustomInternalComparator, createState, strict = false, } = options;
|
|
639
|
+
const config = createEqualityComparatorConfig(options);
|
|
640
|
+
const comparator = createEqualityComparator(config);
|
|
641
|
+
const equals = createCustomInternalComparator
|
|
633
642
|
? createCustomInternalComparator(comparator)
|
|
634
643
|
: createInternalEqualityComparator(comparator);
|
|
635
|
-
return createIsEqual({ circular
|
|
644
|
+
return createIsEqual({ circular, comparator, createState, equals, strict });
|
|
636
645
|
}
|
|
637
646
|
|
|
638
647
|
exports.circularDeepEqual = circularDeepEqual;
|