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.
Files changed (41) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +128 -77
  3. package/dist/cjs/comparator.d.cts +60 -0
  4. package/dist/cjs/{types/equals.d.cts → equals.d.cts} +8 -0
  5. package/dist/cjs/index.cjs +171 -162
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/{types/index.d.cts → index.d.cts} +21 -2
  8. package/{src/internalTypes.ts → dist/cjs/internalTypes.d.cts} +18 -50
  9. package/dist/cjs/{types/utils.d.cts → utils.d.cts} +7 -2
  10. package/dist/es/comparator.d.mts +60 -0
  11. package/dist/{esm/types → es}/equals.d.mts +8 -0
  12. package/dist/{esm/types → es}/index.d.mts +21 -2
  13. package/dist/{esm → es}/index.mjs +171 -162
  14. package/dist/es/index.mjs.map +1 -0
  15. package/dist/es/internalTypes.d.mts +178 -0
  16. package/dist/{esm/types → es}/utils.d.mts +7 -2
  17. package/dist/{min/types → umd}/comparator.d.ts +2 -2
  18. package/dist/{min/types → umd}/equals.d.ts +8 -0
  19. package/dist/umd/index.js +171 -162
  20. package/dist/umd/index.js.map +1 -1
  21. package/dist/{min/types → umd}/internalTypes.d.ts +10 -8
  22. package/index.d.ts +73 -75
  23. package/package.json +45 -48
  24. package/CHANGELOG.md +0 -364
  25. package/dist/cjs/types/comparator.d.cts +0 -26
  26. package/dist/cjs/types/internalTypes.d.cts +0 -157
  27. package/dist/esm/index.mjs.map +0 -1
  28. package/dist/esm/types/comparator.d.mts +0 -26
  29. package/dist/esm/types/internalTypes.d.mts +0 -157
  30. package/dist/min/index.js +0 -1
  31. package/dist/umd/types/comparator.d.ts +0 -26
  32. package/dist/umd/types/equals.d.ts +0 -54
  33. package/dist/umd/types/index.d.ts +0 -47
  34. package/dist/umd/types/internalTypes.d.ts +0 -157
  35. package/dist/umd/types/utils.d.ts +0 -28
  36. package/src/comparator.ts +0 -376
  37. package/src/equals.ts +0 -355
  38. package/src/index.ts +0 -112
  39. package/src/utils.ts +0 -96
  40. /package/dist/{min/types → umd}/index.d.ts +0 -0
  41. /package/dist/{min/types → umd}/utils.d.ts +0 -0
package/src/equals.ts DELETED
@@ -1,355 +0,0 @@
1
- import type {
2
- Dictionary,
3
- PrimitiveWrapper,
4
- State,
5
- TypedArray,
6
- } from './internalTypes.js';
7
- import { getStrictProperties, hasOwn, sameValueZeroEqual } from './utils.js';
8
-
9
- const PREACT_VNODE = '__v';
10
- const PREACT_OWNER = '__o';
11
- const REACT_OWNER = '_owner';
12
-
13
- const { getOwnPropertyDescriptor, keys } = Object;
14
-
15
- /**
16
- * Whether the arrays are equal in value.
17
- */
18
- export function areArraysEqual(a: any[], b: any[], state: State<any>) {
19
- let index = a.length;
20
-
21
- if (b.length !== index) {
22
- return false;
23
- }
24
-
25
- while (index-- > 0) {
26
- if (!state.equals(a[index], b[index], index, index, a, b, state)) {
27
- return false;
28
- }
29
- }
30
-
31
- return true;
32
- }
33
-
34
- /**
35
- * Whether the dates passed are equal in value.
36
- */
37
- export function areDatesEqual(a: Date, b: Date): boolean {
38
- return sameValueZeroEqual(a.getTime(), b.getTime());
39
- }
40
-
41
- /**
42
- * Whether the errors passed are equal in value.
43
- */
44
- export function areErrorsEqual(a: Error, b: Error): boolean {
45
- return (
46
- a.name === b.name &&
47
- a.message === b.message &&
48
- a.cause === b.cause &&
49
- a.stack === b.stack
50
- );
51
- }
52
-
53
- /**
54
- * Whether the functions passed are equal in value.
55
- */
56
- export function areFunctionsEqual(
57
- a: (...args: any[]) => any,
58
- b: (...args: any[]) => any,
59
- ): boolean {
60
- return a === b;
61
- }
62
-
63
- /**
64
- * Whether the `Map`s are equal in value.
65
- */
66
- export function areMapsEqual(
67
- a: Map<any, any>,
68
- b: Map<any, any>,
69
- state: State<any>,
70
- ): boolean {
71
- const size = a.size;
72
-
73
- if (size !== b.size) {
74
- return false;
75
- }
76
-
77
- if (!size) {
78
- return true;
79
- }
80
-
81
- const matchedIndices = new Array<true | undefined>(size);
82
- const aIterable = a.entries();
83
-
84
- let aResult: IteratorResult<[any, any]>;
85
- let bResult: IteratorResult<[any, any]>;
86
- let index = 0;
87
-
88
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
89
- while ((aResult = aIterable.next())) {
90
- if (aResult.done) {
91
- break;
92
- }
93
-
94
- const bIterable = b.entries();
95
-
96
- let hasMatch = false;
97
- let matchIndex = 0;
98
-
99
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
100
- while ((bResult = bIterable.next())) {
101
- if (bResult.done) {
102
- break;
103
- }
104
-
105
- if (matchedIndices[matchIndex]) {
106
- matchIndex++;
107
- continue;
108
- }
109
-
110
- const aEntry = aResult.value;
111
- const bEntry = bResult.value;
112
-
113
- if (
114
- state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state) &&
115
- state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)
116
- ) {
117
- hasMatch = matchedIndices[matchIndex] = true;
118
- break;
119
- }
120
-
121
- matchIndex++;
122
- }
123
-
124
- if (!hasMatch) {
125
- return false;
126
- }
127
-
128
- index++;
129
- }
130
-
131
- return true;
132
- }
133
-
134
- /**
135
- * Whether the numbers are equal in value.
136
- */
137
- export const areNumbersEqual = sameValueZeroEqual;
138
-
139
- /**
140
- * Whether the objects are equal in value.
141
- */
142
- export function areObjectsEqual(
143
- a: Dictionary,
144
- b: Dictionary,
145
- state: State<any>,
146
- ): boolean {
147
- const properties = keys(a);
148
-
149
- let index = properties.length;
150
-
151
- if (keys(b).length !== index) {
152
- return false;
153
- }
154
-
155
- // Decrementing `while` showed faster results than either incrementing or
156
- // decrementing `for` loop and than an incrementing `while` loop. Declarative
157
- // methods like `some` / `every` were not used to avoid incurring the garbage
158
- // cost of anonymous callbacks.
159
- while (index-- > 0) {
160
- if (!isPropertyEqual(a, b, state, properties[index]!)) {
161
- return false;
162
- }
163
- }
164
-
165
- return true;
166
- }
167
-
168
- /**
169
- * Whether the objects are equal in value with strict property checking.
170
- */
171
- export function areObjectsEqualStrict(
172
- a: Dictionary,
173
- b: Dictionary,
174
- state: State<any>,
175
- ): boolean {
176
- const properties = getStrictProperties(a);
177
-
178
- let index = properties.length;
179
-
180
- if (getStrictProperties(b).length !== index) {
181
- return false;
182
- }
183
-
184
- let property: string | symbol;
185
- let descriptorA: ReturnType<typeof getOwnPropertyDescriptor>;
186
- let descriptorB: ReturnType<typeof getOwnPropertyDescriptor>;
187
-
188
- // Decrementing `while` showed faster results than either incrementing or
189
- // decrementing `for` loop and than an incrementing `while` loop. Declarative
190
- // methods like `some` / `every` were not used to avoid incurring the garbage
191
- // cost of anonymous callbacks.
192
- while (index-- > 0) {
193
- property = properties[index]!;
194
-
195
- if (!isPropertyEqual(a, b, state, property)) {
196
- return false;
197
- }
198
-
199
- descriptorA = getOwnPropertyDescriptor(a, property);
200
- descriptorB = getOwnPropertyDescriptor(b, property);
201
-
202
- if (
203
- (descriptorA || descriptorB) &&
204
- (!descriptorA ||
205
- !descriptorB ||
206
- descriptorA.configurable !== descriptorB.configurable ||
207
- descriptorA.enumerable !== descriptorB.enumerable ||
208
- descriptorA.writable !== descriptorB.writable)
209
- ) {
210
- return false;
211
- }
212
- }
213
-
214
- return true;
215
- }
216
-
217
- /**
218
- * Whether the primitive wrappers passed are equal in value.
219
- */
220
- export function arePrimitiveWrappersEqual(
221
- a: PrimitiveWrapper,
222
- b: PrimitiveWrapper,
223
- ): boolean {
224
- return sameValueZeroEqual(a.valueOf(), b.valueOf());
225
- }
226
-
227
- /**
228
- * Whether the regexps passed are equal in value.
229
- */
230
- export function areRegExpsEqual(a: RegExp, b: RegExp): boolean {
231
- return a.source === b.source && a.flags === b.flags;
232
- }
233
-
234
- /**
235
- * Whether the `Set`s are equal in value.
236
- */
237
- export function areSetsEqual(
238
- a: Set<any>,
239
- b: Set<any>,
240
- state: State<any>,
241
- ): boolean {
242
- const size = a.size;
243
-
244
- if (size !== b.size) {
245
- return false;
246
- }
247
-
248
- if (!size) {
249
- return true;
250
- }
251
-
252
- const matchedIndices = new Array<true | undefined>(size);
253
- const aIterable = a.values();
254
-
255
- let aResult: IteratorResult<any>;
256
- let bResult: IteratorResult<any>;
257
-
258
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
259
- while ((aResult = aIterable.next())) {
260
- if (aResult.done) {
261
- break;
262
- }
263
-
264
- const bIterable = b.values();
265
-
266
- let hasMatch = false;
267
- let matchIndex = 0;
268
-
269
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
270
- while ((bResult = bIterable.next())) {
271
- if (bResult.done) {
272
- break;
273
- }
274
-
275
- if (
276
- !matchedIndices[matchIndex] &&
277
- state.equals(
278
- aResult.value,
279
- bResult.value,
280
- aResult.value,
281
- bResult.value,
282
- a,
283
- b,
284
- state,
285
- )
286
- ) {
287
- hasMatch = matchedIndices[matchIndex] = true;
288
- break;
289
- }
290
-
291
- matchIndex++;
292
- }
293
-
294
- if (!hasMatch) {
295
- return false;
296
- }
297
- }
298
-
299
- return true;
300
- }
301
-
302
- /**
303
- * Whether the TypedArray instances are equal in value.
304
- */
305
- export function areTypedArraysEqual(a: TypedArray, b: TypedArray) {
306
- let index = a.length;
307
-
308
- if (b.length !== index) {
309
- return false;
310
- }
311
-
312
- while (index-- > 0) {
313
- if (a[index] !== b[index]) {
314
- return false;
315
- }
316
- }
317
-
318
- return true;
319
- }
320
-
321
- /**
322
- * Whether the URL instances are equal in value.
323
- */
324
- export function areUrlsEqual(a: URL, b: URL): boolean {
325
- return (
326
- a.hostname === b.hostname &&
327
- a.pathname === b.pathname &&
328
- a.protocol === b.protocol &&
329
- a.port === b.port &&
330
- a.hash === b.hash &&
331
- a.username === b.username &&
332
- a.password === b.password
333
- );
334
- }
335
-
336
- function isPropertyEqual(
337
- a: Dictionary,
338
- b: Dictionary,
339
- state: State<any>,
340
- property: string | symbol,
341
- ) {
342
- if (
343
- (property === REACT_OWNER ||
344
- property === PREACT_OWNER ||
345
- property === PREACT_VNODE) &&
346
- (a.$$typeof || b.$$typeof)
347
- ) {
348
- return true;
349
- }
350
-
351
- return (
352
- hasOwn(b, property) &&
353
- state.equals(a[property], b[property], property, property, a, b, state)
354
- );
355
- }
package/src/index.ts DELETED
@@ -1,112 +0,0 @@
1
- import {
2
- createEqualityComparatorConfig,
3
- createEqualityComparator,
4
- createInternalEqualityComparator,
5
- createIsEqual,
6
- } from './comparator.js';
7
- import type { CustomEqualCreatorOptions } from './internalTypes.js';
8
- import { sameValueZeroEqual } from './utils.js';
9
-
10
- export { sameValueZeroEqual };
11
- export type {
12
- AnyEqualityComparator,
13
- Cache,
14
- CircularState,
15
- ComparatorConfig,
16
- CreateCustomComparatorConfig,
17
- CreateState,
18
- CustomEqualCreatorOptions,
19
- DefaultState,
20
- Dictionary,
21
- EqualityComparator,
22
- EqualityComparatorCreator,
23
- InternalEqualityComparator,
24
- PrimitiveWrapper,
25
- State,
26
- TypeEqualityComparator,
27
- TypedArray,
28
- } from './internalTypes.js';
29
-
30
- /**
31
- * Whether the items passed are deeply-equal in value.
32
- */
33
- export const deepEqual = createCustomEqual();
34
-
35
- /**
36
- * Whether the items passed are deeply-equal in value based on strict comparison.
37
- */
38
- export const strictDeepEqual = createCustomEqual({ strict: true });
39
-
40
- /**
41
- * Whether the items passed are deeply-equal in value, including circular references.
42
- */
43
- export const circularDeepEqual = createCustomEqual({ circular: true });
44
-
45
- /**
46
- * Whether the items passed are deeply-equal in value, including circular references,
47
- * based on strict comparison.
48
- */
49
- export const strictCircularDeepEqual = createCustomEqual({
50
- circular: true,
51
- strict: true,
52
- });
53
-
54
- /**
55
- * Whether the items passed are shallowly-equal in value.
56
- */
57
- export const shallowEqual = createCustomEqual({
58
- createInternalComparator: () => sameValueZeroEqual,
59
- });
60
-
61
- /**
62
- * Whether the items passed are shallowly-equal in value based on strict comparison
63
- */
64
- export const strictShallowEqual = createCustomEqual({
65
- strict: true,
66
- createInternalComparator: () => sameValueZeroEqual,
67
- });
68
-
69
- /**
70
- * Whether the items passed are shallowly-equal in value, including circular references.
71
- */
72
- export const circularShallowEqual = createCustomEqual({
73
- circular: true,
74
- createInternalComparator: () => sameValueZeroEqual,
75
- });
76
-
77
- /**
78
- * Whether the items passed are shallowly-equal in value, including circular references,
79
- * based on strict comparison.
80
- */
81
- export const strictCircularShallowEqual = createCustomEqual({
82
- circular: true,
83
- createInternalComparator: () => sameValueZeroEqual,
84
- strict: true,
85
- });
86
-
87
- /**
88
- * Create a custom equality comparison method.
89
- *
90
- * This can be done to create very targeted comparisons in extreme hot-path scenarios
91
- * where the standard methods are not performant enough, but can also be used to provide
92
- * support for legacy environments that do not support expected features like
93
- * `RegExp.prototype.flags` out of the box.
94
- */
95
- export function createCustomEqual<Meta = undefined>(
96
- options: CustomEqualCreatorOptions<Meta> = {},
97
- ) {
98
- const {
99
- circular = false,
100
- createInternalComparator: createCustomInternalComparator,
101
- createState,
102
- strict = false,
103
- } = options;
104
-
105
- const config = createEqualityComparatorConfig<Meta>(options);
106
- const comparator = createEqualityComparator(config);
107
- const equals = createCustomInternalComparator
108
- ? createCustomInternalComparator(comparator)
109
- : createInternalEqualityComparator(comparator);
110
-
111
- return createIsEqual({ circular, comparator, createState, equals, strict });
112
- }
package/src/utils.ts DELETED
@@ -1,96 +0,0 @@
1
- import type {
2
- AnyEqualityComparator,
3
- Cache,
4
- CircularState,
5
- Dictionary,
6
- State,
7
- TypeEqualityComparator,
8
- } from './internalTypes.js';
9
-
10
- const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
11
- const { hasOwnProperty } = Object.prototype;
12
-
13
- /**
14
- * Combine two comparators into a single comparators.
15
- */
16
- export function combineComparators<Meta>(
17
- comparatorA: AnyEqualityComparator<Meta>,
18
- comparatorB: AnyEqualityComparator<Meta>,
19
- ) {
20
- return function isEqual<A, B>(a: A, b: B, state: State<Meta>) {
21
- return comparatorA(a, b, state) && comparatorB(a, b, state);
22
- };
23
- }
24
-
25
- /**
26
- * Wrap the provided `areItemsEqual` method to manage the circular state, allowing
27
- * for circular references to be safely included in the comparison without creating
28
- * stack overflows.
29
- */
30
- export function createIsCircular<
31
- AreItemsEqual extends TypeEqualityComparator<any, any>,
32
- >(areItemsEqual: AreItemsEqual): AreItemsEqual {
33
- return function isCircular(
34
- a: any,
35
- b: any,
36
- state: CircularState<Cache<any, any>>,
37
- ) {
38
- if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
39
- return areItemsEqual(a, b, state);
40
- }
41
-
42
- const { cache } = state;
43
-
44
- const cachedA = cache.get(a);
45
- const cachedB = cache.get(b);
46
-
47
- if (cachedA && cachedB) {
48
- return cachedA === b && cachedB === a;
49
- }
50
-
51
- cache.set(a, b);
52
- cache.set(b, a);
53
-
54
- const result = areItemsEqual(a, b, state);
55
-
56
- cache.delete(a);
57
- cache.delete(b);
58
-
59
- return result;
60
- } as AreItemsEqual;
61
- }
62
-
63
- /**
64
- * Get the `@@toStringTag` of the value, if it exists.
65
- */
66
- export function getShortTag(value: any): string | undefined {
67
- return value != null ? value[Symbol.toStringTag] : undefined;
68
- }
69
-
70
- /**
71
- * Get the properties to strictly examine, which include both own properties that are
72
- * not enumerable and symbol properties.
73
- */
74
- export function getStrictProperties(
75
- object: Dictionary,
76
- ): Array<string | symbol> {
77
- return (getOwnPropertyNames(object) as Array<string | symbol>).concat(
78
- getOwnPropertySymbols(object),
79
- );
80
- }
81
-
82
- /**
83
- * Whether the object contains the property passed as an own property.
84
- */
85
- export const hasOwn =
86
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
87
- Object.hasOwn ||
88
- ((object: Dictionary, property: number | string | symbol) =>
89
- hasOwnProperty.call(object, property));
90
-
91
- /**
92
- * Whether the values passed are strictly equal or both NaN.
93
- */
94
- export function sameValueZeroEqual(a: any, b: any): boolean {
95
- return a === b || (!a && !b && a !== a && b !== b);
96
- }
File without changes
File without changes