fast-equals 3.0.2 → 4.0.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/.prettierrc +4 -0
- package/CHANGELOG.md +35 -0
- package/README.md +60 -44
- package/dist/fast-equals.cjs.js +349 -246
- package/dist/fast-equals.cjs.js.map +1 -1
- package/dist/fast-equals.esm.js +348 -246
- package/dist/fast-equals.esm.js.map +1 -1
- package/dist/fast-equals.js +349 -246
- package/dist/fast-equals.js.map +1 -1
- package/dist/fast-equals.min.js +1 -1
- package/dist/fast-equals.mjs +348 -246
- package/dist/fast-equals.mjs.map +1 -1
- package/index.d.ts +26 -25
- package/package.json +21 -19
- package/recipes/explicit-property-check.md +28 -0
- package/recipes/legacy-circular-equal-support.md +66 -0
- package/recipes/legacy-regexp-support.md +26 -0
- package/recipes/non-standard-properties.md +34 -0
- package/recipes/strict-property-descriptor-check.md +42 -0
- package/recipes/using-meta-in-comparison.md +23 -0
- package/src/arrays.ts +36 -0
- package/src/comparator.ts +146 -0
- package/src/dates.ts +12 -0
- package/src/index.ts +139 -0
- package/src/maps.ts +66 -0
- package/src/objects.ts +61 -0
- package/src/regexps.ts +11 -0
- package/src/sets.ts +61 -0
- package/src/utils.ts +128 -0
package/.prettierrc
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# fast-equals CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
#### Certain ES2015 features are now required
|
|
8
|
+
|
|
9
|
+
In previous versions, there were automatic fallbacks for certain ES2015 features if they did not exist:
|
|
10
|
+
|
|
11
|
+
- [`RegExp.prototype.flags`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags)
|
|
12
|
+
- [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
|
|
13
|
+
|
|
14
|
+
Due to the omnipresence of support in both browser and NodeJS, these have been deprecated. There is still an option if you require support for these legacy environments, however; see [`createCustomEqual`](./README.md#createcustomequal) and [`createCustomCircularEqual`](./README.md#createcustomcircularequal) for more details.
|
|
15
|
+
|
|
16
|
+
#### `createCustomEqual` contract has changed
|
|
17
|
+
|
|
18
|
+
To allow more flexibility and customizability for a variety of edge cases, `createCustomEqual` now allows override of specific type value comparisons in addition to the general comparator it did prior. See [the documentation](./README.md#createcustomequal) for more details.
|
|
19
|
+
|
|
20
|
+
### Enhancements
|
|
21
|
+
|
|
22
|
+
#### `createCustomCircularEqual` added
|
|
23
|
+
|
|
24
|
+
Like `createCustomEqual`, it will create a custom equality comparator, with the exception that it will handle circular references. See [the documentation](./README.md#createcustomcircularequal) for more details.
|
|
25
|
+
|
|
26
|
+
#### Cross-realm comparisons are now supported
|
|
27
|
+
|
|
28
|
+
Prior to `4.x.x.`, `instanceof` was used internally for checking of object classes, which only worked when comparing objects from the same [Realm](https://262.ecma-international.org/6.0/#sec-code-realms). This has changed to instead use an object's [StringTag](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag), which is not realm-specific.
|
|
29
|
+
|
|
30
|
+
#### TypeScript typings improved
|
|
31
|
+
|
|
32
|
+
For better typing in edge-case scenarios like custom comparators with `meta` values, typings have been refactored for accuracy and better narrow flow-through.
|
|
33
|
+
|
|
34
|
+
## 3.0.3
|
|
35
|
+
|
|
36
|
+
- Fix [#77](https://github.com/planttheidea/fast-equals/issues/73) - better circular object validation
|
|
37
|
+
|
|
3
38
|
## 3.0.2
|
|
4
39
|
|
|
5
40
|
- Fix [#73](https://github.com/planttheidea/fast-equals/issues/73) - support comparison of primitive wrappers
|
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 ~
|
|
7
|
+
Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.26kB when minified and gzipped.
|
|
8
8
|
|
|
9
9
|
Unlike most equality validation libraries, the following types are handled out-of-the-box:
|
|
10
10
|
|
|
@@ -31,27 +31,20 @@ Starting with version `1.5.0`, circular objects are supported for both deep and
|
|
|
31
31
|
- [circularDeepEqual](#circulardeepequal)
|
|
32
32
|
- [circularShallowEqual](#circularshallowequal)
|
|
33
33
|
- [createCustomEqual](#createcustomequal)
|
|
34
|
+
- [Recipes](#recipes)
|
|
35
|
+
- [`createCustomCircularEqual`](#createcustomcircularequal)
|
|
36
|
+
- [Recipes](#recipes-1)
|
|
34
37
|
- [Benchmarks](#benchmarks)
|
|
35
38
|
- [Development](#development)
|
|
36
39
|
|
|
37
40
|
## Usage
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```javascript
|
|
42
|
+
```ts
|
|
42
43
|
import { deepEqual } from 'fast-equals';
|
|
43
44
|
|
|
44
45
|
console.log(deepEqual({ foo: 'bar' }, { foo: 'bar' })); // true
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
Or if you want to import all functions under a namespace:
|
|
48
|
-
|
|
49
|
-
```javascript
|
|
50
|
-
import * as fe from 'fast-equals';
|
|
51
|
-
|
|
52
|
-
console.log(fe.deep({ foo: 'bar' }, { foo: 'bar' })); // true
|
|
53
|
-
```
|
|
54
|
-
|
|
55
48
|
### Specific builds
|
|
56
49
|
|
|
57
50
|
There are three builds, an ESM build for modern build systems / runtimes, a CommonJS build for traditional NodeJS environments, and a UMD build for legacy implementations. The ideal one will likely be chosen for you automatically, however if you want to use a specific build you can always import it directly:
|
|
@@ -60,9 +53,6 @@ There are three builds, an ESM build for modern build systems / runtimes, a Comm
|
|
|
60
53
|
- For older `nodejs` versions that do not allow ESM with file extensions other than `.mjs` => `fast-equals/dist/fast-equals.mjs`
|
|
61
54
|
- CommonJS => `fast-equals/dist/fast-equals.cjs.js`
|
|
62
55
|
- UMD => `fast-equals/dist/fast-equals.js`
|
|
63
|
-
|
|
64
|
-
There is also a pre-minified version of the UMD build available:
|
|
65
|
-
|
|
66
56
|
- Minified UMD => `fast-equals/dist/fast-equals.min.js`
|
|
67
57
|
|
|
68
58
|
## Available methods
|
|
@@ -71,7 +61,7 @@ There is also a pre-minified version of the UMD build available:
|
|
|
71
61
|
|
|
72
62
|
Performs a deep equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects.
|
|
73
63
|
|
|
74
|
-
```
|
|
64
|
+
```ts
|
|
75
65
|
import { deepEqual } from 'fast-equals';
|
|
76
66
|
|
|
77
67
|
const objectA = { foo: { bar: 'baz' } };
|
|
@@ -85,7 +75,7 @@ console.log(deepEqual(objectA, objectB)); // true
|
|
|
85
75
|
|
|
86
76
|
`Map` objects support complex keys (objects, Arrays, etc.), however [the spec for key lookups in `Map` are based on `SameZeroValue`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#key_equality). If the spec were followed for comparison, the following would always be `false`:
|
|
87
77
|
|
|
88
|
-
```
|
|
78
|
+
```ts
|
|
89
79
|
const mapA = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]);
|
|
90
80
|
const mapB = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]);
|
|
91
81
|
|
|
@@ -98,7 +88,7 @@ To support true deep equality of all contents, `fast-equals` will perform a deep
|
|
|
98
88
|
|
|
99
89
|
Performs a shallow equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects.
|
|
100
90
|
|
|
101
|
-
```
|
|
91
|
+
```ts
|
|
102
92
|
import { shallowEqual } from 'fast-equals';
|
|
103
93
|
|
|
104
94
|
const nestedObject = { bar: 'baz' };
|
|
@@ -116,7 +106,7 @@ console.log(shallowEqual(objectA, objectC)); // false
|
|
|
116
106
|
|
|
117
107
|
Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) comparison on the two objects passed and returns a boolean representing the value equivalency of the objects. In simple terms, this means either strictly equal or both `NaN`.
|
|
118
108
|
|
|
119
|
-
```
|
|
109
|
+
```ts
|
|
120
110
|
import { sameValueZeroEqual } from 'fast-equals';
|
|
121
111
|
|
|
122
112
|
const mainObject = { foo: NaN, bar: 'baz' };
|
|
@@ -134,7 +124,7 @@ console.log(sameValueZeroEqual(mainObject, objectC)); // false
|
|
|
134
124
|
|
|
135
125
|
Performs the same comparison as `deepEqual` but supports circular objects. It is slower than `deepEqual`, so only use if you know circular objects are present.
|
|
136
126
|
|
|
137
|
-
```
|
|
127
|
+
```ts
|
|
138
128
|
function Circular(value) {
|
|
139
129
|
this.me = {
|
|
140
130
|
deeply: {
|
|
@@ -156,7 +146,7 @@ Just as with `deepEqual`, [both keys and values are compared for deep equality](
|
|
|
156
146
|
|
|
157
147
|
Performs the same comparison as `shallowequal` but supports circular objects. It is slower than `shallowEqual`, so only use if you know circular objects are present.
|
|
158
148
|
|
|
159
|
-
```
|
|
149
|
+
```ts
|
|
160
150
|
const array = ['foo'];
|
|
161
151
|
|
|
162
152
|
array.push(array);
|
|
@@ -167,44 +157,70 @@ console.log(circularShallowEqual(array, [array])); // false
|
|
|
167
157
|
|
|
168
158
|
### createCustomEqual
|
|
169
159
|
|
|
170
|
-
Creates a custom equality comparator that will be used on nested values in the object. Unlike `deepEqual` and `shallowEqual`, this is a
|
|
160
|
+
Creates a custom equality comparator that will be used on nested values in the object. Unlike `deepEqual` and `shallowEqual`, this is a factory method that receives the default options used internally, and allows you to override the defaults as needed. This is generally for extreme edge-cases, or supporting legacy environments.
|
|
171
161
|
|
|
172
162
|
The signature is as follows:
|
|
173
163
|
|
|
174
|
-
```
|
|
175
|
-
type
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
164
|
+
```ts
|
|
165
|
+
type InternalEqualityComparator = (
|
|
166
|
+
a: any,
|
|
167
|
+
b: any,
|
|
168
|
+
indexOrKeyA: any,
|
|
169
|
+
indexOrKeyB: any,
|
|
170
|
+
parentA: any,
|
|
171
|
+
parentB: any,
|
|
172
|
+
meta: any,
|
|
173
|
+
) => boolean;
|
|
174
|
+
|
|
175
|
+
type TypeEqualityComparator = <Type, Meta>(
|
|
176
|
+
a: Type,
|
|
177
|
+
b: Type,
|
|
178
|
+
isEqual: InternalEqualityComparator,
|
|
179
|
+
meta: Meta,
|
|
180
|
+
) => boolean;
|
|
181
|
+
|
|
182
|
+
interface CreateComparatorCreatorOptions<Meta> {
|
|
183
|
+
areArraysEqual: TypeEqualityComparator<any[], Meta>;
|
|
184
|
+
areDatesEqual: TypeEqualityComparator<Date, Meta>;
|
|
185
|
+
areMapsEqual: TypeEqualityComparator<Map<any, any>, Meta>;
|
|
186
|
+
areObjectsEqual: TypeEqualityComparator<Record<string, any>, Meta>;
|
|
187
|
+
areRegExpsEqual: TypeEqualityComparator<RegExp, Meta>;
|
|
188
|
+
areSetsEqual: TypeEqualityComparator<Set<any>, Meta>;
|
|
189
|
+
createIsNestedEqual?: (
|
|
190
|
+
comparator: <A, B>(a: A, b: B, meta: Meta) => boolean,
|
|
191
|
+
) => InternalEqualityComparator;
|
|
192
|
+
}
|
|
180
193
|
|
|
181
194
|
function createCustomEqual(
|
|
182
|
-
|
|
195
|
+
getComparatorOptions: (
|
|
196
|
+
defaultOptions: CreateComparatorOptions,
|
|
197
|
+
) => Partial<CreateComparatorOptions>,
|
|
183
198
|
): EqualityComparator;
|
|
184
199
|
```
|
|
185
200
|
|
|
186
|
-
The `meta` parameter
|
|
201
|
+
The `meta` parameter above is whatever you want it to be. It will be passed through to all equality checks, and is meant specifically for use with custom equality methods. For example, with the `circularDeepEqual` and `circularShallowEqual` methods, it is used to pass through a cache of processed objects. You also only need to return the override handlers; absent being provided, the defaults are used.
|
|
187
202
|
|
|
188
203
|
_**NOTE**: `Map` implementations compare equality for both keys and value. When using a custom comparator and comparing equality of the keys, the iteration index is provided as both `indexOrKeyA` and `indexOrKeyB` to help use-cases where ordering of keys matters to equality._
|
|
189
204
|
|
|
190
|
-
|
|
205
|
+
#### Recipes
|
|
191
206
|
|
|
192
|
-
|
|
193
|
-
import { createCustomEqual } from 'fast-equals';
|
|
207
|
+
Some recipes have been created to provide examples of use-cases for `createCustomEqual`. Even if not directly applicable to the problem you are solving, they can offer guidance of how to structure your solution.
|
|
194
208
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
);
|
|
209
|
+
- [Legacy environment support for `RegExp` comparators](./recipes/legacy-regexp-support.md)
|
|
210
|
+
- [Explicit property check](./recipes/explicit-property-check.md)
|
|
211
|
+
- [Using `meta` in comparison](./recipes//using-meta-in-comparison.md)
|
|
212
|
+
- [Comparing non-standard properties](./recipes/non-standard-properties.md)
|
|
213
|
+
- [Strict property descriptor comparison](./recipes/strict-equality-checks.md)
|
|
201
214
|
|
|
202
|
-
|
|
203
|
-
const objectB = { foo: 'baz' };
|
|
204
|
-
const meta = 'bar';
|
|
215
|
+
### `createCustomCircularEqual`
|
|
205
216
|
|
|
206
|
-
|
|
207
|
-
|
|
217
|
+
Operates nearly identically to [`createCustomEqual`](#createcustomequal), with the difference being that the `meta` property expected by the comparator is expected to have a `WeakMap` contract. This is because it is used for caching accessed objects to avoid maximum stack exceeded errors. The most common use for this method is a simple way to support circular checks for references that do not have `WeakMap` natively.
|
|
218
|
+
|
|
219
|
+
#### Recipes
|
|
220
|
+
|
|
221
|
+
Some recipes have been created to provide examples of use-cases for `createCustomEqual`. Even if not directly applicable to the problem you are solving, they can offer guidance of how to structure your solution.
|
|
222
|
+
|
|
223
|
+
- [Legacy environment support for circualr equal comparators](./recipes/legacy-circular-equal-support.md)
|
|
208
224
|
|
|
209
225
|
## Benchmarks
|
|
210
226
|
|