main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

34
node_modules/fast-equals/.babelrc generated vendored Normal file
View File

@@ -0,0 +1,34 @@
{
"env": {
"lib": {
"presets": [
[
"@babel/preset-env",
{
"loose": true
}
]
]
},
"test": {
"presets": [
[
"@babel/preset-env",
{
"loose": true
}
]
]
}
},
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
"loose": true,
"modules": false
}
]
]
}

8
node_modules/fast-equals/.prettierrc generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"arrowParens": "always",
"bracketSpacing": true,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}

13
node_modules/fast-equals/.release-it.beta.json generated vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"github": {
"release": true,
"tagName": "v${version}"
},
"npm": {
"tag": "next"
},
"preReleaseId": "beta",
"scripts": {
"beforeStart": "npm run prepublish:compile"
}
}

9
node_modules/fast-equals/.release-it.json generated vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"github": {
"release": true,
"tagName": "v${version}"
},
"scripts": {
"beforeStart": "npm run prepublish:compile"
}
}

37
node_modules/fast-equals/BUILD.md generated vendored Normal file
View File

@@ -0,0 +1,37 @@
# Reproducing a build
## Clone version
```
git clone https://github.com/planttheidea/fast-equals.git
cd fast-equals
git checkout {version}
```
Replace `{version}` above with the appropriate package version. If you want to compare a version older than `1.6.2`, you'll need to use a commit hash directly.
## Install
```
yarn install
```
We use `yarn` for our package management, so to ensure that exact dependencies you should also use it.
## Build artifacts
```
yarn run build
```
**NOTE**: To get an exact checksum match with the versions released on npm, it may be necessary to change line endings. For example, on Linux you might run:
```
unix2dos dist/fast-equals.min.js
```
## Get checksum
```
sha256sum dist/fast-equals.min.js
```

291
node_modules/fast-equals/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,291 @@
# fast-equals CHANGELOG
## 5.0.1
### Bugfixes
- Fix reference to `metaOverride` in typings and documentation (holdover from temporary API in v5 beta)
## 5.0.0
### Breaking changes
#### `constructor` equality now required
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.
#### `Map` / `Set` comparisons no longer support IE11
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.
#### `createCustomEqual` contract has changed
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:
- `meta` is no longer passed through to equality comparators, but rather a general `state` object which contains `meta`
- `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
- `equals` is now on `state`, which prevents the need to pass through the separate `isEqual` method for the equality comparator
#### `createCustomCircularEqual` has been removed
You can create a custom circular equality comparator through `createCustomEqual` now by providing `circular: true` to the options.
#### Custom `meta` values are no longer passed at callsite
To use `meta` properties for comparisons, they must be returned in a `createState` method.
#### Deep links have changed
If you were deep-linking into a specific asset type (ESM / CJS / UMD), they have changed location.
**NOTE**: You may no longer need to deep-link, as [the build resolution has improved](#better-build-system-resolution).
### Enhancements
#### New "strict" comparators available
The following new comparators are available:
- `strictDeepEqual`
- `strictShallowEqual`
- `strictCircularDeepEqual`
- `strictCircularShallowEqual`
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.
#### `TypedArray` support
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.
#### Better build system resolution
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.
#### `arePrimitiveWrappersEqual` option added to `createCustomEqual` configuration
If you want a custom comparator for primitive wrappers (`new Boolean()` / `new Number()` / `new String()`) it is now available.
## 4.0.3
- Remove unnecessary second strict equality check for objects in edge-case scenarios
## 4.0.2
- [#85](https://github.com/planttheidea/fast-equals/issues/85) - `createCustomCircularEqual` typing is incorrect
## 4.0.1
- [#81](https://github.com/planttheidea/fast-equals/issues/81) - Fix typing issues related to importing in `index.d.ts` file
## 4.0.0
### Breaking Changes
#### Certain ES2015 features are now required
In previous versions, there were automatic fallbacks for certain ES2015 features if they did not exist:
- [`RegExp.prototype.flags`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags)
- [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
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.
#### `createCustomEqual` contract has changed
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.
### Enhancements
#### `createCustomCircularEqual` added
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.
#### Cross-realm comparisons are now supported
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.
#### TypeScript typings improved
For better typing in edge-case scenarios like custom comparators with `meta` values, typings have been refactored for accuracy and better narrow flow-through.
## 3.0.3
- Fix [#77](https://github.com/planttheidea/fast-equals/issues/73) - better circular object validation
## 3.0.2
- Fix [#73](https://github.com/planttheidea/fast-equals/issues/73) - support comparison of primitive wrappers
- [#76](https://github.com/planttheidea/fast-equals/pull/76) - improve speed and accuracy of `RegExp` comparison in modern environments
## 3.0.1
- Fix [#71](https://github.com/planttheidea/fast-equals/pull/71) - use generic types for better type flow-through
## 3.0.0
### Breaking changes
When creating a custom equality comparator via `createCustomEqual`, the equality method has an expanded contract:
```ts
// Before
type EqualityComparator = (objectA: any, objectB: any, meta: any) => boolean;
// After
type InternalEqualityComparator = (
objectA: any,
objectB: any,
indexOrKeyA: any,
indexOrKeyB: any,
parentA: any,
parentB: any,
meta: any,
) => boolean;
```
If you have a custom equality comparator, you can ignore the differences by just passing additional `undefined` parameters, or you can use the parameters to further improve / clarify the logic.
- Add [#57](https://github.com/planttheidea/fast-equals/pull/57) - support additional metadata for custom equality comparators
## 2.0.4
- Fix [#58](https://github.com/planttheidea/fast-equals/issues/58) - duplicate entries in `Map` / `Set` can create false equality success
- [#60](https://github.com/planttheidea/fast-equals/issues/60) - Add documentation for key equality of `Map` being a part of `deepEqual`
## 2.0.3
- Fix [#50](https://github.com/planttheidea/fast-equals/pull/50) - copy-pasta in cacheable check
## 2.0.2
- Optimize iterables comparisons to not double-iterate
- Optimize loop-based comparisons for speed
- Improve cache handling in circular handlers
- Improve stability of memory by reducing variable instantiation
## 2.0.1
- Fix [#41](https://github.com/planttheidea/fast-equals/pull/41) - prevent `.rpt2_cache` directory from being published for better CI environment support (thanks [@herberttn](https://github.com/herberttn))
## 2.0.0
### Breaking changes
- There are longer `fast-equals/es`, `fast-equals/lib`, `fast-equals/mjs` locations
- Instead, there are 3 builds in `dist` for different consumption types:
- `fast-equals.js` (UMD / `browser`)
- `fast-equals.esm.js` (ESM / `module`)
- `fast-equals.cjs.js` (CommonJS / `main`)
- There is no default export anymore, only the previously-existing named exports
- To get all into a namespace, use `import * as fe from 'fast-equals`
### Updates
- Rewritten completely in TypeScript
- Improve speed of `Map` / `Set` comparisons
- Improve speed of React element comparisons
### Fixes
- Consider pure objects (`Object.create(null)`) to be plain objects
- Fix typings for `createCustomEqual`
## 1.6.3
- Check the size of the iterable before converting to arrays
## 1.6.2
- Fix [#23](https://github.com/planttheidea/fast-equals/issues/23) - false positives for map
- Replace `uglify` with `terser`
- Use `rollup` to build all the distributables (`main`, `module`, and `browser`)
- Maintain `lib` and `es` transpilations in case consumers were deep-linking
## 1.6.1
- Upgrade to `babel@7`
- Add `"sideEffects": false` to `package.json` for better tree-shaking in `webpack`
## 1.6.0
- Add ESM support for NodeJS with separate [`.mjs` extension](https://nodejs.org/api/esm.html) exports
## 1.5.3
- Fix `Map` / `Set` comparison to not require order to match to be equal
## 1.5.2
- Improve speed of object comparison through custom `hasKey` method
## 1.5.1
- Fix lack of support for `unicode` and `sticky` RegExp flag checks
## 1.5.0
- Add [`circularDeepEqual`](README.md#circulardeepequal) and [`circularShallowEqual`](README.md#circularshallowequal) methods
- Add `meta` third parameter to `comparator` calls, for use with `createCustomEqual` method
## 1.4.1
- Fix issue where `lastIndex` was not being tested on `RegExp` objects
## 1.4.0
- Add support for comparing promise-like objects (strict equality only)
## 1.3.1
- Make `react` comparison more accurate, and a touch faster
## 1.3.0
- Add support for deep-equal comparisons between `react` elements
- Add comparison with `react-fast-compare`
- Use `rollup` for `dist` file builds
## 1.2.1
- Fix errors from TypeScript typings in strict mode (thanks [@HitoriSensei](https://github.com/HitoriSensei))
## 1.2.0
- Surface `isSameValueZero` as [`sameValueZeroEqual`](#samevaluezeroequal) option
## 1.1.0
- Add TypeScript typings (thanks [@josh-sachs](https://github.com/josh-sachs))
## 1.0.6
- Support invalid date equality via `isSameValueZero`
## 1.0.5
- Replace `isStrictlyEqual` with `isSameValueZero` to ensure that `shallowEqual` accounts for `NaN` equality
## 1.0.4
- Only check values when comparing `Set` objects (improves performance of `Set` check by ~12%)
## 1.0.3
- Make `Map` and `Set` comparisons more explicit
## 1.0.2
- Fix symmetrical comparison of iterables
- Reduce footprint
## 1.0.1
- Prevent babel transpilation of `typeof` into helper for faster runtime
## 1.0.0
- Initial release
```
```

21
node_modules/fast-equals/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Tony Quetano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

411
node_modules/fast-equals/README.md generated vendored Normal file
View File

@@ -0,0 +1,411 @@
# fast-equals
<img src="https://img.shields.io/badge/build-passing-brightgreen.svg"/>
<img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/>
<img src="https://img.shields.io/badge/license-MIT-blue.svg"/>
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.
The following types are handled out-of-the-box:
- Plain objects (including `react` elements and `Arguments`)
- Arrays
- Typed Arrays
- `Date` objects
- `RegExp` objects
- `Map` / `Set` iterables
- `Promise` objects
- Primitive wrappers (`new Boolean()` / `new Number()` / `new String()`)
- Custom class instances, including subclasses of native classes
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.
## Table of contents
- [fast-equals](#fast-equals)
- [Table of contents](#table-of-contents)
- [Usage](#usage)
- [Specific builds](#specific-builds)
- [Available methods](#available-methods)
- [deepEqual](#deepequal)
- [Comparing `Map`s](#comparing-maps)
- [shallowEqual](#shallowequal)
- [sameValueZeroEqual](#samevaluezeroequal)
- [circularDeepEqual](#circulardeepequal)
- [circularShallowEqual](#circularshallowequal)
- [strictDeepEqual](#strictdeepequal)
- [strictShallowEqual](#strictshallowequal)
- [strictCircularDeepEqual](#strictcirculardeepequal)
- [strictCircularShallowEqual](#strictcircularshallowequal)
- [createCustomEqual](#createcustomequal)
- [Recipes](#recipes)
- [Benchmarks](#benchmarks)
- [Development](#development)
## Usage
```ts
import { deepEqual } from 'fast-equals';
console.log(deepEqual({ foo: 'bar' }, { foo: 'bar' })); // true
```
### Specific builds
By default, npm should resolve the correct build of the package based on your consumption (ESM vs CommonJS). However, if you want to force use of a specific build, they can be located here:
- ESM => `fast-equals/dist/esm/index.mjs`
- CommonJS => `fast-equals/dist/cjs/index.cjs`
- UMD => `fast-equals/dist/umd/index.js`
- Minified UMD => `fast-equals/dist/min/index.js`
If you are having issues loading a specific build type, [please file an issue](https://github.com/planttheidea/fast-equals/issues).
## Available methods
### deepEqual
Performs a deep equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects.
```ts
import { deepEqual } from 'fast-equals';
const objectA = { foo: { bar: 'baz' } };
const objectB = { foo: { bar: 'baz' } };
console.log(objectA === objectB); // false
console.log(deepEqual(objectA, objectB)); // true
```
#### Comparing `Map`s
`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`:
```ts
const mapA = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]);
const mapB = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]);
deepEqual(mapA, mapB);
```
To support true deep equality of all contents, `fast-equals` will perform a deep equality comparison for key and value parirs. Therefore, the above would be `true`.
### shallowEqual
Performs a shallow equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects.
```ts
import { shallowEqual } from 'fast-equals';
const nestedObject = { bar: 'baz' };
const objectA = { foo: nestedObject };
const objectB = { foo: nestedObject };
const objectC = { foo: { bar: 'baz' } };
console.log(objectA === objectB); // false
console.log(shallowEqual(objectA, objectB)); // true
console.log(shallowEqual(objectA, objectC)); // false
```
### sameValueZeroEqual
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`.
```ts
import { sameValueZeroEqual } from 'fast-equals';
const mainObject = { foo: NaN, bar: 'baz' };
const objectA = 'baz';
const objectB = NaN;
const objectC = { foo: NaN, bar: 'baz' };
console.log(sameValueZeroEqual(mainObject.bar, objectA)); // true
console.log(sameValueZeroEqual(mainObject.foo, objectB)); // true
console.log(sameValueZeroEqual(mainObject, objectC)); // false
```
### circularDeepEqual
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.
```ts
function Circular(value) {
this.me = {
deeply: {
nested: {
reference: this,
},
},
value,
};
}
console.log(circularDeepEqual(new Circular('foo'), new Circular('foo'))); // true
console.log(circularDeepEqual(new Circular('foo'), new Circular('bar'))); // false
```
Just as with `deepEqual`, [both keys and values are compared for deep equality](#comparing-maps).
### circularShallowEqual
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.
```ts
const array = ['foo'];
array.push(array);
console.log(circularShallowEqual(array, ['foo', array])); // true
console.log(circularShallowEqual(array, [array])); // false
```
### strictDeepEqual
Performs the same comparison as `deepEqual` but performs a strict comparison of the objects. In this includes:
- Checking symbol properties
- Checking non-enumerable properties in object comparisons
- Checking full descriptor of properties on the object to match
- Checking non-index properties on arrays
- Checking non-key properties on `Map` / `Set` objects
```ts
const array = [{ foo: 'bar' }];
const otherArray = [{ foo: 'bar' }];
array.bar = 'baz';
otherArray.bar = 'baz';
console.log(strictDeepEqual(array, otherArray)); // true;
console.log(strictDeepEqual(array, [{ foo: 'bar' }])); // false;
```
### strictShallowEqual
Performs the same comparison as `shallowEqual` but performs a strict comparison of the objects. In this includes:
- Checking non-enumerable properties in object comparisons
- Checking full descriptor of properties on the object to match
- Checking non-index properties on arrays
- Checking non-key properties on `Map` / `Set` objects
```ts
const array = ['foo'];
const otherArray = ['foo'];
array.bar = 'baz';
otherArray.bar = 'baz';
console.log(strictDeepEqual(array, otherArray)); // true;
console.log(strictDeepEqual(array, ['foo'])); // false;
```
### strictCircularDeepEqual
Performs the same comparison as `circularDeepEqual` but performs a strict comparison of the objects. In this includes:
- Checking `Symbol` properties on the object
- Checking non-enumerable properties in object comparisons
- Checking full descriptor of properties on the object to match
- Checking non-index properties on arrays
- Checking non-key properties on `Map` / `Set` objects
```ts
function Circular(value) {
this.me = {
deeply: {
nested: {
reference: this,
},
},
value,
};
}
const first = new Circular('foo');
Object.defineProperty(first, 'bar', {
enumerable: false,
value: 'baz',
});
const second = new Circular('foo');
Object.defineProperty(second, 'bar', {
enumerable: false,
value: 'baz',
});
console.log(circularDeepEqual(first, second)); // true
console.log(circularDeepEqual(first, new Circular('foo'))); // false
```
### strictCircularShallowEqual
Performs the same comparison as `circularShallowEqual` but performs a strict comparison of the objects. In this includes:
- Checking non-enumerable properties in object comparisons
- Checking full descriptor of properties on the object to match
- Checking non-index properties on arrays
- Checking non-key properties on `Map` / `Set` objects
```ts
const array = ['foo'];
const otherArray = ['foo'];
array.push(array);
otherArray.push(otherArray);
array.bar = 'baz';
otherArray.bar = 'baz';
console.log(circularShallowEqual(array, otherArray)); // true
console.log(circularShallowEqual(array, ['foo', array])); // false
```
### createCustomEqual
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.
The signature is as follows:
```ts
interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
interface ComparatorConfig<Meta> {
areArraysEqual: TypeEqualityComparator<any[], Meta>;
areDatesEqual: TypeEqualityComparator<Date, Meta>;
areMapsEqual: TypeEqualityComparator<Map<any, any>, Meta>;
areObjectsEqual: TypeEqualityComparator<Record<string, any>, Meta>;
arePrimitiveWrappersEqual: TypeEqualityComparator<
boolean | string | number,
Meta
>;
areRegExpsEqual: TypeEqualityComparator<RegExp, Meta>;
areSetsEqual: TypeEqualityComparator<Set<any>, Meta>;
areTypedArraysEqual: TypeEqualityComparatory<TypedArray, Meta>;
}
function createCustomEqual<Meta>(options: {
circular?: boolean;
createCustomConfig?: (
defaultConfig: ComparatorConfig<Meta>,
) => Partial<ComparatorConfig<Meta>>;
createInternalComparator?: (
compare: <A, B>(a: A, b: B, state: State<Meta>) => boolean,
) => (
a: any,
b: any,
indexOrKeyA: any,
indexOrKeyB: any,
parentA: any,
parentB: any,
state: State<Meta>,
) => boolean;
createState?: () => { cache?: Cache; meta?: Meta };
strict?: boolean;
}): <A, B>(a: A, b: B) => boolean;
```
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).
_**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._
#### Recipes
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.
- [Legacy environment support for `RegExp` comparators](./recipes/legacy-regexp-support.md)
- [Explicit property check](./recipes/explicit-property-check.md)
- [Using `meta` in comparison](./recipes//using-meta-in-comparison.md)
- [Comparing non-standard properties](./recipes/non-standard-properties.md)
- [Strict property descriptor comparison](./recipes/strict-property-descriptor-check.md)
- [Legacy environment support for circualr equal comparators](./recipes/legacy-circular-equal-support.md)
## Benchmarks
All benchmarks were performed on an i9-11900H Ubuntu Linux 22.04 laptop with 64GB of memory using NodeJS version `16.14.2`, and are based on averages of running comparisons based deep equality on the following object types:
- Primitives (`String`, `Number`, `null`, `undefined`)
- `Function`
- `Object`
- `Array`
- `Date`
- `RegExp`
- `react` elements
- A mixed object with a combination of all the above types
```bash
Testing mixed objects equal...
┌─────────┬─────────────────────────────────┬────────────────┐
(index) │ Package │ Ops/sec │
├─────────┼─────────────────────────────────┼────────────────┤
0'fast-equals' │ 1249567.730326 │
1'fast-deep-equal' │ 1182463.587514 │
2'react-fast-compare' │ 1152487.319161 │
3'shallow-equal-fuzzy' │ 1092360.712389 │
4'fast-equals (circular)' │ 676669.92003 │
5'underscore.isEqual' │ 429430.837497 │
6'lodash.isEqual' │ 237915.684734 │
7'fast-equals (strict)' │ 181386.38032 │
8'fast-equals (strict circular)' │ 156779.745875 │
9'deep-eql' │ 139155.099209 │
10'deep-equal' │ 1026.527229 │
└─────────┴─────────────────────────────────┴────────────────┘
Testing mixed objects not equal...
┌─────────┬─────────────────────────────────┬────────────────┐
(index) │ Package │ Ops/sec │
├─────────┼─────────────────────────────────┼────────────────┤
0'fast-equals' │ 3255824.097237 │
1'react-fast-compare' │ 2654721.726058 │
2'fast-deep-equal' │ 2582218.974752 │
3'fast-equals (circular)' │ 2474303.26566 │
4'fast-equals (strict)' │ 1088066.604881 │
5'fast-equals (strict circular)' │ 949253.614181 │
6'nano-equal' │ 939170.554148 │
7'underscore.isEqual' │ 738852.197879 │
8'lodash.isEqual' │ 307306.622212 │
9'deep-eql' │ 156250.110401 │
10'assert.deepStrictEqual' │ 22839.454561 │
11'deep-equal' │ 4034.45114 │
└─────────┴─────────────────────────────────┴────────────────┘
```
Caveats that impact the benchmark (and accuracy of comparison):
- `Map`s, `Promise`s, and `Set`s were excluded from the benchmark entirely because no library other than `deep-eql` fully supported their comparison
- `fast-deep-equal`, `react-fast-compare` and `nano-equal` throw on objects with `null` as prototype (`Object.create(null)`)
- `assert.deepStrictEqual` does not support `NaN` or `SameValueZero` equality for dates
- `deep-eql` does not support `SameValueZero` equality for zero equality (positive and negative zero are not equal)
- `deep-equal` does not support `NaN` and does not strictly compare object type, or date / regexp values, nor uses `SameValueZero` equality for dates
- `fast-deep-equal` does not support `NaN` or `SameValueZero` equality for dates
- `nano-equal` does not strictly compare object property structure, array length, or object type, nor `SameValueZero` equality for dates
- `react-fast-compare` does not support `NaN` or `SameValueZero` equality for dates, and does not compare `function` equality
- `shallow-equal-fuzzy` does not strictly compare object type or regexp values, nor `SameValueZero` equality for dates
- `underscore.isEqual` does not support `SameValueZero` equality for primitives or dates
All of these have the potential of inflating the respective library's numbers in comparison to `fast-equals`, but it was the closest apples-to-apples comparison I could create of a reasonable sample size. It should be noted that `react` elements can be circular objects, however simple elements are not; I kept the `react` comparison very basic to allow it to be included.
## Development
Standard practice, clone the repo and `npm i` to get the dependencies. The following npm scripts are available:
- benchmark => run benchmark tests against other equality libraries
- build => build `main`, `module`, and `browser` distributables with `rollup`
- clean => run `rimraf` on the `dist` folder
- dev => start webpack playground App
- dist => run `build`
- lint => run ESLint on all files in `src` folder (also runs on `dev` script)
- lint:fix => run `lint` script, but with auto-fixer
- prepublish:compile => run `lint`, `test:coverage`, `transpile:lib`, `transpile:es`, and `dist` scripts
- start => run `dev`
- test => run AVA with NODE_ENV=test on all files in `test` folder
- test:coverage => run same script as `test` with code coverage calculation via `nyc`
- test:watch => run same script as `test` but keep persistent watcher

49
node_modules/fast-equals/build/rollup/config.base.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import typescript from '@rollup/plugin-typescript';
import fs from 'fs';
import path from 'path';
import tsc from 'typescript';
import { fileURLToPath } from 'url';
const ROOT = fileURLToPath(new URL('../..', import.meta.url));
export const PACKAGE_JSON = JSON.parse(
fs.readFileSync(path.resolve(ROOT, 'package.json')),
);
const external = [
...Object.keys(PACKAGE_JSON.dependencies || {}),
...Object.keys(PACKAGE_JSON.peerDependencies || {}),
];
const globals = external.reduce((globals, name) => {
globals[name] = name;
return globals;
}, {});
export const BASE_CONFIG = {
external,
input: path.resolve(ROOT, 'src', 'index.ts'),
output: {
exports: 'named',
globals,
name: 'fast-equals',
sourcemap: true,
},
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
nodeResolve({
mainFields: ['module', 'browser', 'main'],
}),
commonjs({ include: /use-sync-external-store/ }),
typescript({
tsconfig: path.resolve(ROOT, 'build', 'tsconfig', 'base.json'),
typescript: tsc,
}),
],
};

10
node_modules/fast-equals/build/rollup/config.cjs.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import { BASE_CONFIG, PACKAGE_JSON } from './config.base.js';
export default {
...BASE_CONFIG,
output: {
...BASE_CONFIG.output,
file: PACKAGE_JSON.main,
format: 'cjs',
},
};

10
node_modules/fast-equals/build/rollup/config.esm.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import { BASE_CONFIG, PACKAGE_JSON } from './config.base.js';
export default {
...BASE_CONFIG,
output: {
...BASE_CONFIG.output,
file: PACKAGE_JSON.module,
format: 'es',
},
};

13
node_modules/fast-equals/build/rollup/config.min.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import { BASE_CONFIG, PACKAGE_JSON } from './config.base.js';
import terser from '@rollup/plugin-terser';
export default {
...BASE_CONFIG,
output: {
...BASE_CONFIG.output,
file: PACKAGE_JSON.browser.replace('umd', 'min'),
format: 'umd',
sourcemap: false,
},
plugins: [...BASE_CONFIG.plugins, terser()],
};

10
node_modules/fast-equals/build/rollup/config.umd.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import { BASE_CONFIG, PACKAGE_JSON } from './config.base.js';
export default {
...BASE_CONFIG,
output: {
...BASE_CONFIG.output,
file: PACKAGE_JSON.browser,
format: 'umd',
},
};

32
node_modules/fast-equals/build/tsconfig/base.json generated vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"compilerOptions": {
"allowJs": true,
"allowUnreachableCode": false,
"baseUrl": "../../src",
"esModuleInterop": true,
"jsx": "react-jsx",
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"moduleResolution": "Node",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "../../../dist",
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"strictBindCallApply": true,
"strictNullChecks": true,
"inlineSources": true,
"target": "es5",
"types": ["jest", "node", "react"]
},
"exclude": ["../../node_modules"],
"include": ["../../src/**/*", "../../__tests__/**/*", "../../DEV_ONLY/**/*"],
"files": ["../../node_modules/jest-expect-message/types/index.d.ts"]
}

8
node_modules/fast-equals/build/tsconfig/cjs.json generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./declarations.json",
"compilerOptions": {
"declarationDir": "../../dist/cjs/types",
"module": "CommonJS",
"outDir": "../../dist/cjs"
}
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./base.json",
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
"resolveJsonModule": false
},
"include": ["../../src/*"]
}

8
node_modules/fast-equals/build/tsconfig/esm.json generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./declarations.json",
"compilerOptions": {
"declarationDir": "../../dist/esm/types",
"module": "ESNext",
"outDir": "../../dist/esm"
}
}

8
node_modules/fast-equals/build/tsconfig/min.json generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./declarations.json",
"compilerOptions": {
"declarationDir": "../../dist/min/types",
"module": "UMD",
"outDir": "../../dist/min"
}
}

8
node_modules/fast-equals/build/tsconfig/umd.json generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./declarations.json",
"compilerOptions": {
"declarationDir": "../../dist/umd/types",
"module": "UMD",
"outDir": "../../dist/umd"
}
}

57
node_modules/fast-equals/build/webpack.config.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import path from 'path';
import { fileURLToPath } from 'url';
import webpack from 'webpack';
const ROOT = fileURLToPath(new URL('..', import.meta.url));
const PORT = 3000;
export default {
cache: true,
devServer: {
host: 'localhost',
port: PORT,
},
devtool: 'source-map',
entry: [path.resolve(ROOT, 'DEV_ONLY', 'index.tsx')],
mode: 'development',
module: {
rules: [
{
include: [path.resolve(ROOT, 'src'), path.resolve(ROOT, 'DEV_ONLY')],
loader: 'ts-loader',
options: {
reportFiles: ['src/*.{ts|tsx}'],
},
test: /\.(ts|tsx)$/,
},
],
},
output: {
filename: 'fast-equals.js',
library: 'fastEquals',
libraryTarget: 'umd',
path: path.resolve(ROOT, 'dist'),
publicPath: `http://localhost:${PORT}/`,
umdNamedDefine: true,
},
plugins: [
new ESLintWebpackPlugin(),
new webpack.EnvironmentPlugin(['NODE_ENV']),
new HtmlWebpackPlugin(),
],
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};

553
node_modules/fast-equals/dist/cjs/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,553 @@
'use strict';
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Combine two comparators into a single comparators.
*/
function combineComparators(comparatorA, comparatorB) {
return function isEqual(a, b, state) {
return comparatorA(a, b, state) && comparatorB(a, b, state);
};
}
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
function createIsCircular(areItemsEqual) {
return function isCircular(a, b, state) {
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return areItemsEqual(a, b, state);
}
var cache = state.cache;
var cachedA = cache.get(a);
var cachedB = cache.get(b);
if (cachedA && cachedB) {
return cachedA === b && cachedB === a;
}
cache.set(a, b);
cache.set(b, a);
var result = areItemsEqual(a, b, state);
cache.delete(a);
cache.delete(b);
return result;
};
}
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
function getStrictProperties(object) {
return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
}
/**
* Whether the object contains the property passed as an own property.
*/
var hasOwn = Object.hasOwn ||
(function (object, property) {
return hasOwnProperty.call(object, property);
});
/**
* Whether the values passed are strictly equal or both NaN.
*/
function sameValueZeroEqual(a, b) {
return a || b ? a === b : a === b || (a !== a && b !== b);
}
var OWNER = '_owner';
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys = Object.keys;
/**
* Whether the arrays are equal in value.
*/
function areArraysEqual(a, b, state) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (!state.equals(a[index], b[index], index, index, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the dates passed are equal in value.
*/
function areDatesEqual(a, b) {
return sameValueZeroEqual(a.getTime(), b.getTime());
}
/**
* Whether the `Map`s are equal in value.
*/
function areMapsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.entries();
var index = 0;
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.entries();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
var _a = aResult.value, aKey = _a[0], aValue = _a[1];
var _b = bResult.value, bKey = _b[0], bValue = _b[1];
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch =
state.equals(aKey, bKey, index, matchIndex, a, b, state) &&
state.equals(aValue, bValue, aKey, bKey, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
index++;
}
return true;
}
/**
* Whether the objects are equal in value.
*/
function areObjectsEqual(a, b, state) {
var properties = keys(a);
var index = properties.length;
if (keys(b).length !== index) {
return false;
}
var property;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property) ||
!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the objects are equal in value with strict property checking.
*/
function areObjectsEqualStrict(a, b, state) {
var properties = getStrictProperties(a);
var index = properties.length;
if (getStrictProperties(b).length !== index) {
return false;
}
var property;
var descriptorA;
var descriptorB;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property)) {
return false;
}
if (!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
descriptorA = getOwnPropertyDescriptor(a, property);
descriptorB = getOwnPropertyDescriptor(b, property);
if ((descriptorA || descriptorB) &&
(!descriptorA ||
!descriptorB ||
descriptorA.configurable !== descriptorB.configurable ||
descriptorA.enumerable !== descriptorB.enumerable ||
descriptorA.writable !== descriptorB.writable)) {
return false;
}
}
return true;
}
/**
* Whether the primitive wrappers passed are equal in value.
*/
function arePrimitiveWrappersEqual(a, b) {
return sameValueZeroEqual(a.valueOf(), b.valueOf());
}
/**
* Whether the regexps passed are equal in value.
*/
function areRegExpsEqual(a, b) {
return a.source === b.source && a.flags === b.flags;
}
/**
* Whether the `Set`s are equal in value.
*/
function areSetsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.values();
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.values();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
}
return true;
}
/**
* Whether the TypedArray instances are equal in value.
*/
function areTypedArraysEqual(a, b) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (a[index] !== b[index]) {
return false;
}
}
return true;
}
var ARGUMENTS_TAG = '[object Arguments]';
var BOOLEAN_TAG = '[object Boolean]';
var DATE_TAG = '[object Date]';
var MAP_TAG = '[object Map]';
var NUMBER_TAG = '[object Number]';
var OBJECT_TAG = '[object Object]';
var REG_EXP_TAG = '[object RegExp]';
var SET_TAG = '[object Set]';
var STRING_TAG = '[object String]';
var isArray = Array.isArray;
var isTypedArray = typeof ArrayBuffer === 'function' && ArrayBuffer.isView
? ArrayBuffer.isView
: null;
var assign = Object.assign;
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
function createEqualityComparator(_a) {
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;
/**
* compare the value of the two objects and return true if they are equivalent in values
*/
return function comparator(a, b, state) {
// If the items are strictly equal, no need to do a value comparison.
if (a === b) {
return true;
}
// If the items are not non-nullish objects, then the only possibility
// of them being equal but not strictly is if they are both `NaN`. Since
// `NaN` is uniquely not equal to itself, we can use self-comparison of
// both objects, which is faster than `isNaN()`.
if (a == null ||
b == null ||
typeof a !== 'object' ||
typeof b !== 'object') {
return a !== a && b !== b;
}
var constructor = a.constructor;
// Checks are listed in order of commonality of use-case:
// 1. Common complex object types (plain object, array)
// 2. Common data values (date, regexp)
// 3. Less-common complex object types (map, set)
// 4. Less-common data values (promise, primitive wrappers)
// Inherently this is both subjective and assumptive, however
// when reviewing comparable libraries in the wild this order
// appears to be generally consistent.
// Constructors should match, otherwise there is potential for false positives
// between class and subclass or custom object and POJO.
if (constructor !== b.constructor) {
return false;
}
// `isPlainObject` only checks against the object's own realm. Cross-realm
// comparisons are rare, and will be handled in the ultimate fallback, so
// we can avoid capturing the string tag.
if (constructor === Object) {
return areObjectsEqual(a, b, state);
}
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
// the string tag or doing an `instanceof` check.
if (isArray(a)) {
return areArraysEqual(a, b, state);
}
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
// capturing the string tag or comparing against all possible constructors.
if (isTypedArray != null && isTypedArray(a)) {
return areTypedArraysEqual(a, b, state);
}
// Try to fast-path equality checks for other complex object types in the
// same realm to avoid capturing the string tag. Strict equality is used
// instead of `instanceof` because it is more performant for the common
// use-case. If someone is subclassing a native class, it will be handled
// with the string tag comparison.
if (constructor === Date) {
return areDatesEqual(a, b, state);
}
if (constructor === RegExp) {
return areRegExpsEqual(a, b, state);
}
if (constructor === Map) {
return areMapsEqual(a, b, state);
}
if (constructor === Set) {
return areSetsEqual(a, b, state);
}
// Since this is a custom object, capture the string tag to determing its type.
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
var tag = getTag(a);
if (tag === DATE_TAG) {
return areDatesEqual(a, b, state);
}
if (tag === REG_EXP_TAG) {
return areRegExpsEqual(a, b, state);
}
if (tag === MAP_TAG) {
return areMapsEqual(a, b, state);
}
if (tag === SET_TAG) {
return areSetsEqual(a, b, state);
}
if (tag === OBJECT_TAG) {
// The exception for value comparison is custom `Promise`-like class instances. These should
// be treated the same as standard `Promise` objects, which means strict equality, and if
// it reaches this point then that strict equality comparison has already failed.
return (typeof a.then !== 'function' &&
typeof b.then !== 'function' &&
areObjectsEqual(a, b, state));
}
// If an arguments tag, it should be treated as a standard object.
if (tag === ARGUMENTS_TAG) {
return areObjectsEqual(a, b, state);
}
// As the penultimate fallback, check if the values passed are primitive wrappers. This
// is very rare in modern JS, which is why it is deprioritized compared to all other object
// types.
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
return arePrimitiveWrappersEqual(a, b, state);
}
// If not matching any tags that require a specific type of comparison, then we hard-code false because
// the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
// - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
// comparison that can be made.
// - For types that can be introspected, but rarely have requirements to be compared
// (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
// use-cases (may be included in a future release, if requested enough).
// - For types that can be introspected but do not have an objective definition of what
// equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
// In all cases, these decisions should be reevaluated based on changes to the language and
// common development practices.
return false;
};
}
/**
* Create the configuration object used for building comparators.
*/
function createEqualityComparatorConfig(_a) {
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
var config = {
areArraysEqual: strict
? areObjectsEqualStrict
: areArraysEqual,
areDatesEqual: areDatesEqual,
areMapsEqual: strict
? combineComparators(areMapsEqual, areObjectsEqualStrict)
: areMapsEqual,
areObjectsEqual: strict
? areObjectsEqualStrict
: areObjectsEqual,
arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
areRegExpsEqual: areRegExpsEqual,
areSetsEqual: strict
? combineComparators(areSetsEqual, areObjectsEqualStrict)
: areSetsEqual,
areTypedArraysEqual: strict
? areObjectsEqualStrict
: areTypedArraysEqual,
};
if (createCustomConfig) {
config = assign({}, config, createCustomConfig(config));
}
if (circular) {
var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
config = assign({}, config, {
areArraysEqual: areArraysEqual$1,
areMapsEqual: areMapsEqual$1,
areObjectsEqual: areObjectsEqual$1,
areSetsEqual: areSetsEqual$1,
});
}
return config;
}
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
function createInternalEqualityComparator(compare) {
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
return compare(a, b, state);
};
}
/**
* Create the `isEqual` function used by the consuming application.
*/
function createIsEqual(_a) {
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
if (createState) {
return function isEqual(a, b) {
var _a = createState(), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, meta = _a.meta;
return comparator(a, b, {
cache: cache,
equals: equals,
meta: meta,
strict: strict,
});
};
}
if (circular) {
return function isEqual(a, b) {
return comparator(a, b, {
cache: new WeakMap(),
equals: equals,
meta: undefined,
strict: strict,
});
};
}
var state = {
cache: undefined,
equals: equals,
meta: undefined,
strict: strict,
};
return function isEqual(a, b) {
return comparator(a, b, state);
};
}
/**
* Whether the items passed are deeply-equal in value.
*/
var deepEqual = createCustomEqual();
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
var strictDeepEqual = createCustomEqual({ strict: true });
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
var circularDeepEqual = createCustomEqual({ circular: true });
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularDeepEqual = createCustomEqual({
circular: true,
strict: true,
});
/**
* Whether the items passed are shallowly-equal in value.
*/
var shallowEqual = createCustomEqual({
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
var strictShallowEqual = createCustomEqual({
strict: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
var circularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
strict: true,
});
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
function createCustomEqual(options) {
if (options === void 0) { options = {}; }
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;
var config = createEqualityComparatorConfig(options);
var comparator = createEqualityComparator(config);
var equals = createCustomInternalComparator
? createCustomInternalComparator(comparator)
: createInternalEqualityComparator(comparator);
return createIsEqual({ circular: circular, comparator: comparator, createState: createState, equals: equals, strict: strict });
}
exports.circularDeepEqual = circularDeepEqual;
exports.circularShallowEqual = circularShallowEqual;
exports.createCustomEqual = createCustomEqual;
exports.deepEqual = deepEqual;
exports.sameValueZeroEqual = sameValueZeroEqual;
exports.shallowEqual = shallowEqual;
exports.strictCircularDeepEqual = strictCircularDeepEqual;
exports.strictCircularShallowEqual = strictCircularShallowEqual;
exports.strictDeepEqual = strictDeepEqual;
exports.strictShallowEqual = strictShallowEqual;
//# sourceMappingURL=index.cjs.map

1
node_modules/fast-equals/dist/cjs/index.cjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
import type { ComparatorConfig, CreateState, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator } from './internalTypes';
interface CreateIsEqualOptions<Meta> {
circular: boolean;
comparator: EqualityComparator<Meta>;
createState: CreateState<Meta> | undefined;
equals: InternalEqualityComparator<Meta>;
strict: boolean;
}
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
export declare function createEqualityComparator<Meta>({ areArraysEqual, areDatesEqual, areMapsEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, }: ComparatorConfig<Meta>): EqualityComparator<Meta>;
/**
* Create the configuration object used for building comparators.
*/
export declare function createEqualityComparatorConfig<Meta>({ circular, createCustomConfig, strict, }: CustomEqualCreatorOptions<Meta>): ComparatorConfig<Meta>;
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
export declare function createInternalEqualityComparator<Meta>(compare: EqualityComparator<Meta>): InternalEqualityComparator<Meta>;
/**
* Create the `isEqual` function used by the consuming application.
*/
export declare function createIsEqual<Meta>({ circular, comparator, createState, equals, strict, }: CreateIsEqualOptions<Meta>): <A, B>(a: A, b: B) => boolean;
export {};

37
node_modules/fast-equals/dist/cjs/types/equals.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import type { Dictionary, PrimitiveWrapper, State, TypedArray } from './internalTypes';
/**
* Whether the arrays are equal in value.
*/
export declare function areArraysEqual(a: any[], b: any[], state: State<any>): boolean;
/**
* Whether the dates passed are equal in value.
*/
export declare function areDatesEqual(a: Date, b: Date): boolean;
/**
* Whether the `Map`s are equal in value.
*/
export declare function areMapsEqual(a: Map<any, any>, b: Map<any, any>, state: State<any>): boolean;
/**
* Whether the objects are equal in value.
*/
export declare function areObjectsEqual(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the objects are equal in value with strict property checking.
*/
export declare function areObjectsEqualStrict(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the primitive wrappers passed are equal in value.
*/
export declare function arePrimitiveWrappersEqual(a: PrimitiveWrapper, b: PrimitiveWrapper): boolean;
/**
* Whether the regexps passed are equal in value.
*/
export declare function areRegExpsEqual(a: RegExp, b: RegExp): boolean;
/**
* Whether the `Set`s are equal in value.
*/
export declare function areSetsEqual(a: Set<any>, b: Set<any>, state: State<any>): boolean;
/**
* Whether the TypedArray instances are equal in value.
*/
export declare function areTypedArraysEqual(a: TypedArray, b: TypedArray): boolean;

47
node_modules/fast-equals/dist/cjs/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import type { CustomEqualCreatorOptions } from './internalTypes';
import { sameValueZeroEqual } from './utils';
export { sameValueZeroEqual };
export * from './internalTypes';
/**
* Whether the items passed are deeply-equal in value.
*/
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value.
*/
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
export declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;

View File

@@ -0,0 +1,134 @@
/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
export interface State<Meta> {
/**
* Cache used to identify circular references
*/
readonly cache: Cache<any, any> | undefined;
/**
* Method used to determine equality of nested value.
*/
readonly equals: InternalEqualityComparator<Meta>;
/**
* Additional value that can be used for comparisons.
*/
meta: Meta;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
readonly strict: boolean;
}
export interface CircularState<Meta> extends State<Meta> {
readonly cache: Cache<any, any>;
}
export interface DefaultState<Meta> extends State<Meta> {
readonly cache: undefined;
}
export interface Dictionary<Value = any> {
[key: string | symbol]: Value;
$$typeof?: any;
}
export interface ComparatorConfig<Meta> {
/**
* Whether the arrays passed are equal in value. In strict mode, this includes
* additional properties added to the array.
*/
areArraysEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the dates passed are equal in value.
*/
areDatesEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the maps passed are equal in value. In strict mode, this includes
* additional properties added to the map.
*/
areMapsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the objects passed are equal in value. In strict mode, this includes
* non-enumerable properties added to the map, as well as symbol properties.
*/
areObjectsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the primitive wrappers passed are equal in value.
*/
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the regexps passed are equal in value.
*/
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the sets passed are equal in value. In strict mode, this includes
* additional properties added to the set.
*/
areSetsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the typed arrays passed are equal in value. In strict mode, this includes
* additional properties added to the typed array.
*/
areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
}
export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
export type CreateState<Meta> = () => {
cache?: Cache<any, any> | undefined;
meta?: Meta;
};
export type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
export type PrimitiveWrapper = Boolean | Number | String;
/**
* Type which encompasses possible instances of TypedArray
* classes.
*
* **NOTE**: This does not include `BigInt64Array` and
* `BitUint64Array` because those are part of ES2020 and
* not supported by certain TS configurations. If using
* either in `areTypedArraysEqual`, you can cast the
* instance as `TypedArray` and it will work as expected,
* because runtime checks will still work for those classes.
*/
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
export interface CustomEqualCreatorOptions<Meta> {
/**
* Whether circular references should be supported. It causes the
* comparison to be slower, but for objects that have circular references
* it is required to avoid stack overflows.
*/
circular?: boolean;
/**
* Create a custom configuration of type-specific equality comparators.
* This receives the default configuration, which allows either replacement
* or supersetting of the default methods.
*/
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
/**
* Create a custom internal comparator, which is used as an override to the
* default entry point for nested value equality comparisons. This is often
* used for doing custom logic for specific types (such as handling a specific
* class instance differently than other objects) or to incorporate `meta` in
* the comparison. See the recipes for examples.
*/
createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
/**
* Create a custom `state` object passed between the methods. This allows for
* custom `cache` and/or `meta` values to be used.
*/
createState?: CreateState<Meta>;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
strict?: boolean;
}

24
node_modules/fast-equals/dist/cjs/types/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { AnyEqualityComparator, Dictionary, State, TypeEqualityComparator } from './internalTypes';
/**
* Combine two comparators into a single comparators.
*/
export declare function combineComparators<Meta>(comparatorA: AnyEqualityComparator<Meta>, comparatorB: AnyEqualityComparator<Meta>): <A, B>(a: A, b: B, state: State<Meta>) => boolean;
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
export declare function createIsCircular<AreItemsEqual extends TypeEqualityComparator<any, any>>(areItemsEqual: AreItemsEqual): AreItemsEqual;
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
export declare function getStrictProperties(object: Dictionary): Array<string | symbol>;
/**
* Whether the object contains the property passed as an own property.
*/
export declare const hasOwn: (o: object, v: PropertyKey) => boolean;
/**
* Whether the values passed are strictly equal or both NaN.
*/
export declare function sameValueZeroEqual(a: any, b: any): boolean;

542
node_modules/fast-equals/dist/esm/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,542 @@
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Combine two comparators into a single comparators.
*/
function combineComparators(comparatorA, comparatorB) {
return function isEqual(a, b, state) {
return comparatorA(a, b, state) && comparatorB(a, b, state);
};
}
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
function createIsCircular(areItemsEqual) {
return function isCircular(a, b, state) {
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return areItemsEqual(a, b, state);
}
var cache = state.cache;
var cachedA = cache.get(a);
var cachedB = cache.get(b);
if (cachedA && cachedB) {
return cachedA === b && cachedB === a;
}
cache.set(a, b);
cache.set(b, a);
var result = areItemsEqual(a, b, state);
cache.delete(a);
cache.delete(b);
return result;
};
}
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
function getStrictProperties(object) {
return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
}
/**
* Whether the object contains the property passed as an own property.
*/
var hasOwn = Object.hasOwn ||
(function (object, property) {
return hasOwnProperty.call(object, property);
});
/**
* Whether the values passed are strictly equal or both NaN.
*/
function sameValueZeroEqual(a, b) {
return a || b ? a === b : a === b || (a !== a && b !== b);
}
var OWNER = '_owner';
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys = Object.keys;
/**
* Whether the arrays are equal in value.
*/
function areArraysEqual(a, b, state) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (!state.equals(a[index], b[index], index, index, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the dates passed are equal in value.
*/
function areDatesEqual(a, b) {
return sameValueZeroEqual(a.getTime(), b.getTime());
}
/**
* Whether the `Map`s are equal in value.
*/
function areMapsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.entries();
var index = 0;
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.entries();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
var _a = aResult.value, aKey = _a[0], aValue = _a[1];
var _b = bResult.value, bKey = _b[0], bValue = _b[1];
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch =
state.equals(aKey, bKey, index, matchIndex, a, b, state) &&
state.equals(aValue, bValue, aKey, bKey, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
index++;
}
return true;
}
/**
* Whether the objects are equal in value.
*/
function areObjectsEqual(a, b, state) {
var properties = keys(a);
var index = properties.length;
if (keys(b).length !== index) {
return false;
}
var property;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property) ||
!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the objects are equal in value with strict property checking.
*/
function areObjectsEqualStrict(a, b, state) {
var properties = getStrictProperties(a);
var index = properties.length;
if (getStrictProperties(b).length !== index) {
return false;
}
var property;
var descriptorA;
var descriptorB;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property)) {
return false;
}
if (!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
descriptorA = getOwnPropertyDescriptor(a, property);
descriptorB = getOwnPropertyDescriptor(b, property);
if ((descriptorA || descriptorB) &&
(!descriptorA ||
!descriptorB ||
descriptorA.configurable !== descriptorB.configurable ||
descriptorA.enumerable !== descriptorB.enumerable ||
descriptorA.writable !== descriptorB.writable)) {
return false;
}
}
return true;
}
/**
* Whether the primitive wrappers passed are equal in value.
*/
function arePrimitiveWrappersEqual(a, b) {
return sameValueZeroEqual(a.valueOf(), b.valueOf());
}
/**
* Whether the regexps passed are equal in value.
*/
function areRegExpsEqual(a, b) {
return a.source === b.source && a.flags === b.flags;
}
/**
* Whether the `Set`s are equal in value.
*/
function areSetsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.values();
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.values();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
}
return true;
}
/**
* Whether the TypedArray instances are equal in value.
*/
function areTypedArraysEqual(a, b) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (a[index] !== b[index]) {
return false;
}
}
return true;
}
var ARGUMENTS_TAG = '[object Arguments]';
var BOOLEAN_TAG = '[object Boolean]';
var DATE_TAG = '[object Date]';
var MAP_TAG = '[object Map]';
var NUMBER_TAG = '[object Number]';
var OBJECT_TAG = '[object Object]';
var REG_EXP_TAG = '[object RegExp]';
var SET_TAG = '[object Set]';
var STRING_TAG = '[object String]';
var isArray = Array.isArray;
var isTypedArray = typeof ArrayBuffer === 'function' && ArrayBuffer.isView
? ArrayBuffer.isView
: null;
var assign = Object.assign;
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
function createEqualityComparator(_a) {
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;
/**
* compare the value of the two objects and return true if they are equivalent in values
*/
return function comparator(a, b, state) {
// If the items are strictly equal, no need to do a value comparison.
if (a === b) {
return true;
}
// If the items are not non-nullish objects, then the only possibility
// of them being equal but not strictly is if they are both `NaN`. Since
// `NaN` is uniquely not equal to itself, we can use self-comparison of
// both objects, which is faster than `isNaN()`.
if (a == null ||
b == null ||
typeof a !== 'object' ||
typeof b !== 'object') {
return a !== a && b !== b;
}
var constructor = a.constructor;
// Checks are listed in order of commonality of use-case:
// 1. Common complex object types (plain object, array)
// 2. Common data values (date, regexp)
// 3. Less-common complex object types (map, set)
// 4. Less-common data values (promise, primitive wrappers)
// Inherently this is both subjective and assumptive, however
// when reviewing comparable libraries in the wild this order
// appears to be generally consistent.
// Constructors should match, otherwise there is potential for false positives
// between class and subclass or custom object and POJO.
if (constructor !== b.constructor) {
return false;
}
// `isPlainObject` only checks against the object's own realm. Cross-realm
// comparisons are rare, and will be handled in the ultimate fallback, so
// we can avoid capturing the string tag.
if (constructor === Object) {
return areObjectsEqual(a, b, state);
}
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
// the string tag or doing an `instanceof` check.
if (isArray(a)) {
return areArraysEqual(a, b, state);
}
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
// capturing the string tag or comparing against all possible constructors.
if (isTypedArray != null && isTypedArray(a)) {
return areTypedArraysEqual(a, b, state);
}
// Try to fast-path equality checks for other complex object types in the
// same realm to avoid capturing the string tag. Strict equality is used
// instead of `instanceof` because it is more performant for the common
// use-case. If someone is subclassing a native class, it will be handled
// with the string tag comparison.
if (constructor === Date) {
return areDatesEqual(a, b, state);
}
if (constructor === RegExp) {
return areRegExpsEqual(a, b, state);
}
if (constructor === Map) {
return areMapsEqual(a, b, state);
}
if (constructor === Set) {
return areSetsEqual(a, b, state);
}
// Since this is a custom object, capture the string tag to determing its type.
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
var tag = getTag(a);
if (tag === DATE_TAG) {
return areDatesEqual(a, b, state);
}
if (tag === REG_EXP_TAG) {
return areRegExpsEqual(a, b, state);
}
if (tag === MAP_TAG) {
return areMapsEqual(a, b, state);
}
if (tag === SET_TAG) {
return areSetsEqual(a, b, state);
}
if (tag === OBJECT_TAG) {
// The exception for value comparison is custom `Promise`-like class instances. These should
// be treated the same as standard `Promise` objects, which means strict equality, and if
// it reaches this point then that strict equality comparison has already failed.
return (typeof a.then !== 'function' &&
typeof b.then !== 'function' &&
areObjectsEqual(a, b, state));
}
// If an arguments tag, it should be treated as a standard object.
if (tag === ARGUMENTS_TAG) {
return areObjectsEqual(a, b, state);
}
// As the penultimate fallback, check if the values passed are primitive wrappers. This
// is very rare in modern JS, which is why it is deprioritized compared to all other object
// types.
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
return arePrimitiveWrappersEqual(a, b, state);
}
// If not matching any tags that require a specific type of comparison, then we hard-code false because
// the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
// - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
// comparison that can be made.
// - For types that can be introspected, but rarely have requirements to be compared
// (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
// use-cases (may be included in a future release, if requested enough).
// - For types that can be introspected but do not have an objective definition of what
// equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
// In all cases, these decisions should be reevaluated based on changes to the language and
// common development practices.
return false;
};
}
/**
* Create the configuration object used for building comparators.
*/
function createEqualityComparatorConfig(_a) {
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
var config = {
areArraysEqual: strict
? areObjectsEqualStrict
: areArraysEqual,
areDatesEqual: areDatesEqual,
areMapsEqual: strict
? combineComparators(areMapsEqual, areObjectsEqualStrict)
: areMapsEqual,
areObjectsEqual: strict
? areObjectsEqualStrict
: areObjectsEqual,
arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
areRegExpsEqual: areRegExpsEqual,
areSetsEqual: strict
? combineComparators(areSetsEqual, areObjectsEqualStrict)
: areSetsEqual,
areTypedArraysEqual: strict
? areObjectsEqualStrict
: areTypedArraysEqual,
};
if (createCustomConfig) {
config = assign({}, config, createCustomConfig(config));
}
if (circular) {
var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
config = assign({}, config, {
areArraysEqual: areArraysEqual$1,
areMapsEqual: areMapsEqual$1,
areObjectsEqual: areObjectsEqual$1,
areSetsEqual: areSetsEqual$1,
});
}
return config;
}
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
function createInternalEqualityComparator(compare) {
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
return compare(a, b, state);
};
}
/**
* Create the `isEqual` function used by the consuming application.
*/
function createIsEqual(_a) {
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
if (createState) {
return function isEqual(a, b) {
var _a = createState(), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, meta = _a.meta;
return comparator(a, b, {
cache: cache,
equals: equals,
meta: meta,
strict: strict,
});
};
}
if (circular) {
return function isEqual(a, b) {
return comparator(a, b, {
cache: new WeakMap(),
equals: equals,
meta: undefined,
strict: strict,
});
};
}
var state = {
cache: undefined,
equals: equals,
meta: undefined,
strict: strict,
};
return function isEqual(a, b) {
return comparator(a, b, state);
};
}
/**
* Whether the items passed are deeply-equal in value.
*/
var deepEqual = createCustomEqual();
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
var strictDeepEqual = createCustomEqual({ strict: true });
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
var circularDeepEqual = createCustomEqual({ circular: true });
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularDeepEqual = createCustomEqual({
circular: true,
strict: true,
});
/**
* Whether the items passed are shallowly-equal in value.
*/
var shallowEqual = createCustomEqual({
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
var strictShallowEqual = createCustomEqual({
strict: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
var circularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
strict: true,
});
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
function createCustomEqual(options) {
if (options === void 0) { options = {}; }
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;
var config = createEqualityComparatorConfig(options);
var comparator = createEqualityComparator(config);
var equals = createCustomInternalComparator
? createCustomInternalComparator(comparator)
: createInternalEqualityComparator(comparator);
return createIsEqual({ circular: circular, comparator: comparator, createState: createState, equals: equals, strict: strict });
}
export { circularDeepEqual, circularShallowEqual, createCustomEqual, deepEqual, sameValueZeroEqual, shallowEqual, strictCircularDeepEqual, strictCircularShallowEqual, strictDeepEqual, strictShallowEqual };
//# sourceMappingURL=index.mjs.map

1
node_modules/fast-equals/dist/esm/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
import type { ComparatorConfig, CreateState, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator } from './internalTypes';
interface CreateIsEqualOptions<Meta> {
circular: boolean;
comparator: EqualityComparator<Meta>;
createState: CreateState<Meta> | undefined;
equals: InternalEqualityComparator<Meta>;
strict: boolean;
}
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
export declare function createEqualityComparator<Meta>({ areArraysEqual, areDatesEqual, areMapsEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, }: ComparatorConfig<Meta>): EqualityComparator<Meta>;
/**
* Create the configuration object used for building comparators.
*/
export declare function createEqualityComparatorConfig<Meta>({ circular, createCustomConfig, strict, }: CustomEqualCreatorOptions<Meta>): ComparatorConfig<Meta>;
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
export declare function createInternalEqualityComparator<Meta>(compare: EqualityComparator<Meta>): InternalEqualityComparator<Meta>;
/**
* Create the `isEqual` function used by the consuming application.
*/
export declare function createIsEqual<Meta>({ circular, comparator, createState, equals, strict, }: CreateIsEqualOptions<Meta>): <A, B>(a: A, b: B) => boolean;
export {};

37
node_modules/fast-equals/dist/esm/types/equals.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import type { Dictionary, PrimitiveWrapper, State, TypedArray } from './internalTypes';
/**
* Whether the arrays are equal in value.
*/
export declare function areArraysEqual(a: any[], b: any[], state: State<any>): boolean;
/**
* Whether the dates passed are equal in value.
*/
export declare function areDatesEqual(a: Date, b: Date): boolean;
/**
* Whether the `Map`s are equal in value.
*/
export declare function areMapsEqual(a: Map<any, any>, b: Map<any, any>, state: State<any>): boolean;
/**
* Whether the objects are equal in value.
*/
export declare function areObjectsEqual(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the objects are equal in value with strict property checking.
*/
export declare function areObjectsEqualStrict(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the primitive wrappers passed are equal in value.
*/
export declare function arePrimitiveWrappersEqual(a: PrimitiveWrapper, b: PrimitiveWrapper): boolean;
/**
* Whether the regexps passed are equal in value.
*/
export declare function areRegExpsEqual(a: RegExp, b: RegExp): boolean;
/**
* Whether the `Set`s are equal in value.
*/
export declare function areSetsEqual(a: Set<any>, b: Set<any>, state: State<any>): boolean;
/**
* Whether the TypedArray instances are equal in value.
*/
export declare function areTypedArraysEqual(a: TypedArray, b: TypedArray): boolean;

47
node_modules/fast-equals/dist/esm/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import type { CustomEqualCreatorOptions } from './internalTypes';
import { sameValueZeroEqual } from './utils';
export { sameValueZeroEqual };
export * from './internalTypes';
/**
* Whether the items passed are deeply-equal in value.
*/
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value.
*/
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
export declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;

View File

@@ -0,0 +1,134 @@
/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
export interface State<Meta> {
/**
* Cache used to identify circular references
*/
readonly cache: Cache<any, any> | undefined;
/**
* Method used to determine equality of nested value.
*/
readonly equals: InternalEqualityComparator<Meta>;
/**
* Additional value that can be used for comparisons.
*/
meta: Meta;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
readonly strict: boolean;
}
export interface CircularState<Meta> extends State<Meta> {
readonly cache: Cache<any, any>;
}
export interface DefaultState<Meta> extends State<Meta> {
readonly cache: undefined;
}
export interface Dictionary<Value = any> {
[key: string | symbol]: Value;
$$typeof?: any;
}
export interface ComparatorConfig<Meta> {
/**
* Whether the arrays passed are equal in value. In strict mode, this includes
* additional properties added to the array.
*/
areArraysEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the dates passed are equal in value.
*/
areDatesEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the maps passed are equal in value. In strict mode, this includes
* additional properties added to the map.
*/
areMapsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the objects passed are equal in value. In strict mode, this includes
* non-enumerable properties added to the map, as well as symbol properties.
*/
areObjectsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the primitive wrappers passed are equal in value.
*/
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the regexps passed are equal in value.
*/
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the sets passed are equal in value. In strict mode, this includes
* additional properties added to the set.
*/
areSetsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the typed arrays passed are equal in value. In strict mode, this includes
* additional properties added to the typed array.
*/
areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
}
export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
export type CreateState<Meta> = () => {
cache?: Cache<any, any> | undefined;
meta?: Meta;
};
export type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
export type PrimitiveWrapper = Boolean | Number | String;
/**
* Type which encompasses possible instances of TypedArray
* classes.
*
* **NOTE**: This does not include `BigInt64Array` and
* `BitUint64Array` because those are part of ES2020 and
* not supported by certain TS configurations. If using
* either in `areTypedArraysEqual`, you can cast the
* instance as `TypedArray` and it will work as expected,
* because runtime checks will still work for those classes.
*/
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
export interface CustomEqualCreatorOptions<Meta> {
/**
* Whether circular references should be supported. It causes the
* comparison to be slower, but for objects that have circular references
* it is required to avoid stack overflows.
*/
circular?: boolean;
/**
* Create a custom configuration of type-specific equality comparators.
* This receives the default configuration, which allows either replacement
* or supersetting of the default methods.
*/
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
/**
* Create a custom internal comparator, which is used as an override to the
* default entry point for nested value equality comparisons. This is often
* used for doing custom logic for specific types (such as handling a specific
* class instance differently than other objects) or to incorporate `meta` in
* the comparison. See the recipes for examples.
*/
createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
/**
* Create a custom `state` object passed between the methods. This allows for
* custom `cache` and/or `meta` values to be used.
*/
createState?: CreateState<Meta>;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
strict?: boolean;
}

24
node_modules/fast-equals/dist/esm/types/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { AnyEqualityComparator, Dictionary, State, TypeEqualityComparator } from './internalTypes';
/**
* Combine two comparators into a single comparators.
*/
export declare function combineComparators<Meta>(comparatorA: AnyEqualityComparator<Meta>, comparatorB: AnyEqualityComparator<Meta>): <A, B>(a: A, b: B, state: State<Meta>) => boolean;
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
export declare function createIsCircular<AreItemsEqual extends TypeEqualityComparator<any, any>>(areItemsEqual: AreItemsEqual): AreItemsEqual;
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
export declare function getStrictProperties(object: Dictionary): Array<string | symbol>;
/**
* Whether the object contains the property passed as an own property.
*/
export declare const hasOwn: (o: object, v: PropertyKey) => boolean;
/**
* Whether the values passed are strictly equal or both NaN.
*/
export declare function sameValueZeroEqual(a: any, b: any): boolean;

1
node_modules/fast-equals/dist/min/index.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
import type { ComparatorConfig, CreateState, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator } from './internalTypes';
interface CreateIsEqualOptions<Meta> {
circular: boolean;
comparator: EqualityComparator<Meta>;
createState: CreateState<Meta> | undefined;
equals: InternalEqualityComparator<Meta>;
strict: boolean;
}
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
export declare function createEqualityComparator<Meta>({ areArraysEqual, areDatesEqual, areMapsEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, }: ComparatorConfig<Meta>): EqualityComparator<Meta>;
/**
* Create the configuration object used for building comparators.
*/
export declare function createEqualityComparatorConfig<Meta>({ circular, createCustomConfig, strict, }: CustomEqualCreatorOptions<Meta>): ComparatorConfig<Meta>;
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
export declare function createInternalEqualityComparator<Meta>(compare: EqualityComparator<Meta>): InternalEqualityComparator<Meta>;
/**
* Create the `isEqual` function used by the consuming application.
*/
export declare function createIsEqual<Meta>({ circular, comparator, createState, equals, strict, }: CreateIsEqualOptions<Meta>): <A, B>(a: A, b: B) => boolean;
export {};

37
node_modules/fast-equals/dist/min/types/equals.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import type { Dictionary, PrimitiveWrapper, State, TypedArray } from './internalTypes';
/**
* Whether the arrays are equal in value.
*/
export declare function areArraysEqual(a: any[], b: any[], state: State<any>): boolean;
/**
* Whether the dates passed are equal in value.
*/
export declare function areDatesEqual(a: Date, b: Date): boolean;
/**
* Whether the `Map`s are equal in value.
*/
export declare function areMapsEqual(a: Map<any, any>, b: Map<any, any>, state: State<any>): boolean;
/**
* Whether the objects are equal in value.
*/
export declare function areObjectsEqual(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the objects are equal in value with strict property checking.
*/
export declare function areObjectsEqualStrict(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the primitive wrappers passed are equal in value.
*/
export declare function arePrimitiveWrappersEqual(a: PrimitiveWrapper, b: PrimitiveWrapper): boolean;
/**
* Whether the regexps passed are equal in value.
*/
export declare function areRegExpsEqual(a: RegExp, b: RegExp): boolean;
/**
* Whether the `Set`s are equal in value.
*/
export declare function areSetsEqual(a: Set<any>, b: Set<any>, state: State<any>): boolean;
/**
* Whether the TypedArray instances are equal in value.
*/
export declare function areTypedArraysEqual(a: TypedArray, b: TypedArray): boolean;

47
node_modules/fast-equals/dist/min/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import type { CustomEqualCreatorOptions } from './internalTypes';
import { sameValueZeroEqual } from './utils';
export { sameValueZeroEqual };
export * from './internalTypes';
/**
* Whether the items passed are deeply-equal in value.
*/
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value.
*/
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
export declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;

View File

@@ -0,0 +1,134 @@
/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
export interface State<Meta> {
/**
* Cache used to identify circular references
*/
readonly cache: Cache<any, any> | undefined;
/**
* Method used to determine equality of nested value.
*/
readonly equals: InternalEqualityComparator<Meta>;
/**
* Additional value that can be used for comparisons.
*/
meta: Meta;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
readonly strict: boolean;
}
export interface CircularState<Meta> extends State<Meta> {
readonly cache: Cache<any, any>;
}
export interface DefaultState<Meta> extends State<Meta> {
readonly cache: undefined;
}
export interface Dictionary<Value = any> {
[key: string | symbol]: Value;
$$typeof?: any;
}
export interface ComparatorConfig<Meta> {
/**
* Whether the arrays passed are equal in value. In strict mode, this includes
* additional properties added to the array.
*/
areArraysEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the dates passed are equal in value.
*/
areDatesEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the maps passed are equal in value. In strict mode, this includes
* additional properties added to the map.
*/
areMapsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the objects passed are equal in value. In strict mode, this includes
* non-enumerable properties added to the map, as well as symbol properties.
*/
areObjectsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the primitive wrappers passed are equal in value.
*/
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the regexps passed are equal in value.
*/
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the sets passed are equal in value. In strict mode, this includes
* additional properties added to the set.
*/
areSetsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the typed arrays passed are equal in value. In strict mode, this includes
* additional properties added to the typed array.
*/
areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
}
export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
export type CreateState<Meta> = () => {
cache?: Cache<any, any> | undefined;
meta?: Meta;
};
export type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
export type PrimitiveWrapper = Boolean | Number | String;
/**
* Type which encompasses possible instances of TypedArray
* classes.
*
* **NOTE**: This does not include `BigInt64Array` and
* `BitUint64Array` because those are part of ES2020 and
* not supported by certain TS configurations. If using
* either in `areTypedArraysEqual`, you can cast the
* instance as `TypedArray` and it will work as expected,
* because runtime checks will still work for those classes.
*/
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
export interface CustomEqualCreatorOptions<Meta> {
/**
* Whether circular references should be supported. It causes the
* comparison to be slower, but for objects that have circular references
* it is required to avoid stack overflows.
*/
circular?: boolean;
/**
* Create a custom configuration of type-specific equality comparators.
* This receives the default configuration, which allows either replacement
* or supersetting of the default methods.
*/
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
/**
* Create a custom internal comparator, which is used as an override to the
* default entry point for nested value equality comparisons. This is often
* used for doing custom logic for specific types (such as handling a specific
* class instance differently than other objects) or to incorporate `meta` in
* the comparison. See the recipes for examples.
*/
createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
/**
* Create a custom `state` object passed between the methods. This allows for
* custom `cache` and/or `meta` values to be used.
*/
createState?: CreateState<Meta>;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
strict?: boolean;
}

24
node_modules/fast-equals/dist/min/types/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { AnyEqualityComparator, Dictionary, State, TypeEqualityComparator } from './internalTypes';
/**
* Combine two comparators into a single comparators.
*/
export declare function combineComparators<Meta>(comparatorA: AnyEqualityComparator<Meta>, comparatorB: AnyEqualityComparator<Meta>): <A, B>(a: A, b: B, state: State<Meta>) => boolean;
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
export declare function createIsCircular<AreItemsEqual extends TypeEqualityComparator<any, any>>(areItemsEqual: AreItemsEqual): AreItemsEqual;
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
export declare function getStrictProperties(object: Dictionary): Array<string | symbol>;
/**
* Whether the object contains the property passed as an own property.
*/
export declare const hasOwn: (o: object, v: PropertyKey) => boolean;
/**
* Whether the values passed are strictly equal or both NaN.
*/
export declare function sameValueZeroEqual(a: any, b: any): boolean;

559
node_modules/fast-equals/dist/umd/index.js generated vendored Normal file
View File

@@ -0,0 +1,559 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["fast-equals"] = {}));
})(this, (function (exports) { 'use strict';
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Combine two comparators into a single comparators.
*/
function combineComparators(comparatorA, comparatorB) {
return function isEqual(a, b, state) {
return comparatorA(a, b, state) && comparatorB(a, b, state);
};
}
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
function createIsCircular(areItemsEqual) {
return function isCircular(a, b, state) {
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return areItemsEqual(a, b, state);
}
var cache = state.cache;
var cachedA = cache.get(a);
var cachedB = cache.get(b);
if (cachedA && cachedB) {
return cachedA === b && cachedB === a;
}
cache.set(a, b);
cache.set(b, a);
var result = areItemsEqual(a, b, state);
cache.delete(a);
cache.delete(b);
return result;
};
}
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
function getStrictProperties(object) {
return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
}
/**
* Whether the object contains the property passed as an own property.
*/
var hasOwn = Object.hasOwn ||
(function (object, property) {
return hasOwnProperty.call(object, property);
});
/**
* Whether the values passed are strictly equal or both NaN.
*/
function sameValueZeroEqual(a, b) {
return a || b ? a === b : a === b || (a !== a && b !== b);
}
var OWNER = '_owner';
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys = Object.keys;
/**
* Whether the arrays are equal in value.
*/
function areArraysEqual(a, b, state) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (!state.equals(a[index], b[index], index, index, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the dates passed are equal in value.
*/
function areDatesEqual(a, b) {
return sameValueZeroEqual(a.getTime(), b.getTime());
}
/**
* Whether the `Map`s are equal in value.
*/
function areMapsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.entries();
var index = 0;
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.entries();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
var _a = aResult.value, aKey = _a[0], aValue = _a[1];
var _b = bResult.value, bKey = _b[0], bValue = _b[1];
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch =
state.equals(aKey, bKey, index, matchIndex, a, b, state) &&
state.equals(aValue, bValue, aKey, bKey, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
index++;
}
return true;
}
/**
* Whether the objects are equal in value.
*/
function areObjectsEqual(a, b, state) {
var properties = keys(a);
var index = properties.length;
if (keys(b).length !== index) {
return false;
}
var property;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property) ||
!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the objects are equal in value with strict property checking.
*/
function areObjectsEqualStrict(a, b, state) {
var properties = getStrictProperties(a);
var index = properties.length;
if (getStrictProperties(b).length !== index) {
return false;
}
var property;
var descriptorA;
var descriptorB;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index];
if (property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof) {
return false;
}
if (!hasOwn(b, property)) {
return false;
}
if (!state.equals(a[property], b[property], property, property, a, b, state)) {
return false;
}
descriptorA = getOwnPropertyDescriptor(a, property);
descriptorB = getOwnPropertyDescriptor(b, property);
if ((descriptorA || descriptorB) &&
(!descriptorA ||
!descriptorB ||
descriptorA.configurable !== descriptorB.configurable ||
descriptorA.enumerable !== descriptorB.enumerable ||
descriptorA.writable !== descriptorB.writable)) {
return false;
}
}
return true;
}
/**
* Whether the primitive wrappers passed are equal in value.
*/
function arePrimitiveWrappersEqual(a, b) {
return sameValueZeroEqual(a.valueOf(), b.valueOf());
}
/**
* Whether the regexps passed are equal in value.
*/
function areRegExpsEqual(a, b) {
return a.source === b.source && a.flags === b.flags;
}
/**
* Whether the `Set`s are equal in value.
*/
function areSetsEqual(a, b, state) {
if (a.size !== b.size) {
return false;
}
var matchedIndices = {};
var aIterable = a.values();
var aResult;
var bResult;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
var bIterable = b.values();
var hasMatch = false;
var matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
if (!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
}
return true;
}
/**
* Whether the TypedArray instances are equal in value.
*/
function areTypedArraysEqual(a, b) {
var index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (a[index] !== b[index]) {
return false;
}
}
return true;
}
var ARGUMENTS_TAG = '[object Arguments]';
var BOOLEAN_TAG = '[object Boolean]';
var DATE_TAG = '[object Date]';
var MAP_TAG = '[object Map]';
var NUMBER_TAG = '[object Number]';
var OBJECT_TAG = '[object Object]';
var REG_EXP_TAG = '[object RegExp]';
var SET_TAG = '[object Set]';
var STRING_TAG = '[object String]';
var isArray = Array.isArray;
var isTypedArray = typeof ArrayBuffer === 'function' && ArrayBuffer.isView
? ArrayBuffer.isView
: null;
var assign = Object.assign;
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
function createEqualityComparator(_a) {
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;
/**
* compare the value of the two objects and return true if they are equivalent in values
*/
return function comparator(a, b, state) {
// If the items are strictly equal, no need to do a value comparison.
if (a === b) {
return true;
}
// If the items are not non-nullish objects, then the only possibility
// of them being equal but not strictly is if they are both `NaN`. Since
// `NaN` is uniquely not equal to itself, we can use self-comparison of
// both objects, which is faster than `isNaN()`.
if (a == null ||
b == null ||
typeof a !== 'object' ||
typeof b !== 'object') {
return a !== a && b !== b;
}
var constructor = a.constructor;
// Checks are listed in order of commonality of use-case:
// 1. Common complex object types (plain object, array)
// 2. Common data values (date, regexp)
// 3. Less-common complex object types (map, set)
// 4. Less-common data values (promise, primitive wrappers)
// Inherently this is both subjective and assumptive, however
// when reviewing comparable libraries in the wild this order
// appears to be generally consistent.
// Constructors should match, otherwise there is potential for false positives
// between class and subclass or custom object and POJO.
if (constructor !== b.constructor) {
return false;
}
// `isPlainObject` only checks against the object's own realm. Cross-realm
// comparisons are rare, and will be handled in the ultimate fallback, so
// we can avoid capturing the string tag.
if (constructor === Object) {
return areObjectsEqual(a, b, state);
}
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
// the string tag or doing an `instanceof` check.
if (isArray(a)) {
return areArraysEqual(a, b, state);
}
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
// capturing the string tag or comparing against all possible constructors.
if (isTypedArray != null && isTypedArray(a)) {
return areTypedArraysEqual(a, b, state);
}
// Try to fast-path equality checks for other complex object types in the
// same realm to avoid capturing the string tag. Strict equality is used
// instead of `instanceof` because it is more performant for the common
// use-case. If someone is subclassing a native class, it will be handled
// with the string tag comparison.
if (constructor === Date) {
return areDatesEqual(a, b, state);
}
if (constructor === RegExp) {
return areRegExpsEqual(a, b, state);
}
if (constructor === Map) {
return areMapsEqual(a, b, state);
}
if (constructor === Set) {
return areSetsEqual(a, b, state);
}
// Since this is a custom object, capture the string tag to determing its type.
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
var tag = getTag(a);
if (tag === DATE_TAG) {
return areDatesEqual(a, b, state);
}
if (tag === REG_EXP_TAG) {
return areRegExpsEqual(a, b, state);
}
if (tag === MAP_TAG) {
return areMapsEqual(a, b, state);
}
if (tag === SET_TAG) {
return areSetsEqual(a, b, state);
}
if (tag === OBJECT_TAG) {
// The exception for value comparison is custom `Promise`-like class instances. These should
// be treated the same as standard `Promise` objects, which means strict equality, and if
// it reaches this point then that strict equality comparison has already failed.
return (typeof a.then !== 'function' &&
typeof b.then !== 'function' &&
areObjectsEqual(a, b, state));
}
// If an arguments tag, it should be treated as a standard object.
if (tag === ARGUMENTS_TAG) {
return areObjectsEqual(a, b, state);
}
// As the penultimate fallback, check if the values passed are primitive wrappers. This
// is very rare in modern JS, which is why it is deprioritized compared to all other object
// types.
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
return arePrimitiveWrappersEqual(a, b, state);
}
// If not matching any tags that require a specific type of comparison, then we hard-code false because
// the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
// - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
// comparison that can be made.
// - For types that can be introspected, but rarely have requirements to be compared
// (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
// use-cases (may be included in a future release, if requested enough).
// - For types that can be introspected but do not have an objective definition of what
// equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
// In all cases, these decisions should be reevaluated based on changes to the language and
// common development practices.
return false;
};
}
/**
* Create the configuration object used for building comparators.
*/
function createEqualityComparatorConfig(_a) {
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
var config = {
areArraysEqual: strict
? areObjectsEqualStrict
: areArraysEqual,
areDatesEqual: areDatesEqual,
areMapsEqual: strict
? combineComparators(areMapsEqual, areObjectsEqualStrict)
: areMapsEqual,
areObjectsEqual: strict
? areObjectsEqualStrict
: areObjectsEqual,
arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
areRegExpsEqual: areRegExpsEqual,
areSetsEqual: strict
? combineComparators(areSetsEqual, areObjectsEqualStrict)
: areSetsEqual,
areTypedArraysEqual: strict
? areObjectsEqualStrict
: areTypedArraysEqual,
};
if (createCustomConfig) {
config = assign({}, config, createCustomConfig(config));
}
if (circular) {
var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
config = assign({}, config, {
areArraysEqual: areArraysEqual$1,
areMapsEqual: areMapsEqual$1,
areObjectsEqual: areObjectsEqual$1,
areSetsEqual: areSetsEqual$1,
});
}
return config;
}
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
function createInternalEqualityComparator(compare) {
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
return compare(a, b, state);
};
}
/**
* Create the `isEqual` function used by the consuming application.
*/
function createIsEqual(_a) {
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
if (createState) {
return function isEqual(a, b) {
var _a = createState(), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, meta = _a.meta;
return comparator(a, b, {
cache: cache,
equals: equals,
meta: meta,
strict: strict,
});
};
}
if (circular) {
return function isEqual(a, b) {
return comparator(a, b, {
cache: new WeakMap(),
equals: equals,
meta: undefined,
strict: strict,
});
};
}
var state = {
cache: undefined,
equals: equals,
meta: undefined,
strict: strict,
};
return function isEqual(a, b) {
return comparator(a, b, state);
};
}
/**
* Whether the items passed are deeply-equal in value.
*/
var deepEqual = createCustomEqual();
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
var strictDeepEqual = createCustomEqual({ strict: true });
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
var circularDeepEqual = createCustomEqual({ circular: true });
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularDeepEqual = createCustomEqual({
circular: true,
strict: true,
});
/**
* Whether the items passed are shallowly-equal in value.
*/
var shallowEqual = createCustomEqual({
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
var strictShallowEqual = createCustomEqual({
strict: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
var circularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
});
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
var strictCircularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: function () { return sameValueZeroEqual; },
strict: true,
});
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
function createCustomEqual(options) {
if (options === void 0) { options = {}; }
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;
var config = createEqualityComparatorConfig(options);
var comparator = createEqualityComparator(config);
var equals = createCustomInternalComparator
? createCustomInternalComparator(comparator)
: createInternalEqualityComparator(comparator);
return createIsEqual({ circular: circular, comparator: comparator, createState: createState, equals: equals, strict: strict });
}
exports.circularDeepEqual = circularDeepEqual;
exports.circularShallowEqual = circularShallowEqual;
exports.createCustomEqual = createCustomEqual;
exports.deepEqual = deepEqual;
exports.sameValueZeroEqual = sameValueZeroEqual;
exports.shallowEqual = shallowEqual;
exports.strictCircularDeepEqual = strictCircularDeepEqual;
exports.strictCircularShallowEqual = strictCircularShallowEqual;
exports.strictDeepEqual = strictDeepEqual;
exports.strictShallowEqual = strictShallowEqual;
}));
//# sourceMappingURL=index.js.map

1
node_modules/fast-equals/dist/umd/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
import type { ComparatorConfig, CreateState, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator } from './internalTypes';
interface CreateIsEqualOptions<Meta> {
circular: boolean;
comparator: EqualityComparator<Meta>;
createState: CreateState<Meta> | undefined;
equals: InternalEqualityComparator<Meta>;
strict: boolean;
}
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
export declare function createEqualityComparator<Meta>({ areArraysEqual, areDatesEqual, areMapsEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, }: ComparatorConfig<Meta>): EqualityComparator<Meta>;
/**
* Create the configuration object used for building comparators.
*/
export declare function createEqualityComparatorConfig<Meta>({ circular, createCustomConfig, strict, }: CustomEqualCreatorOptions<Meta>): ComparatorConfig<Meta>;
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
export declare function createInternalEqualityComparator<Meta>(compare: EqualityComparator<Meta>): InternalEqualityComparator<Meta>;
/**
* Create the `isEqual` function used by the consuming application.
*/
export declare function createIsEqual<Meta>({ circular, comparator, createState, equals, strict, }: CreateIsEqualOptions<Meta>): <A, B>(a: A, b: B) => boolean;
export {};

37
node_modules/fast-equals/dist/umd/types/equals.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import type { Dictionary, PrimitiveWrapper, State, TypedArray } from './internalTypes';
/**
* Whether the arrays are equal in value.
*/
export declare function areArraysEqual(a: any[], b: any[], state: State<any>): boolean;
/**
* Whether the dates passed are equal in value.
*/
export declare function areDatesEqual(a: Date, b: Date): boolean;
/**
* Whether the `Map`s are equal in value.
*/
export declare function areMapsEqual(a: Map<any, any>, b: Map<any, any>, state: State<any>): boolean;
/**
* Whether the objects are equal in value.
*/
export declare function areObjectsEqual(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the objects are equal in value with strict property checking.
*/
export declare function areObjectsEqualStrict(a: Dictionary, b: Dictionary, state: State<any>): boolean;
/**
* Whether the primitive wrappers passed are equal in value.
*/
export declare function arePrimitiveWrappersEqual(a: PrimitiveWrapper, b: PrimitiveWrapper): boolean;
/**
* Whether the regexps passed are equal in value.
*/
export declare function areRegExpsEqual(a: RegExp, b: RegExp): boolean;
/**
* Whether the `Set`s are equal in value.
*/
export declare function areSetsEqual(a: Set<any>, b: Set<any>, state: State<any>): boolean;
/**
* Whether the TypedArray instances are equal in value.
*/
export declare function areTypedArraysEqual(a: TypedArray, b: TypedArray): boolean;

47
node_modules/fast-equals/dist/umd/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import type { CustomEqualCreatorOptions } from './internalTypes';
import { sameValueZeroEqual } from './utils';
export { sameValueZeroEqual };
export * from './internalTypes';
/**
* Whether the items passed are deeply-equal in value.
*/
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value.
*/
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
export declare function createCustomEqual<Meta = undefined>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B) => boolean;

View File

@@ -0,0 +1,134 @@
/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
export interface State<Meta> {
/**
* Cache used to identify circular references
*/
readonly cache: Cache<any, any> | undefined;
/**
* Method used to determine equality of nested value.
*/
readonly equals: InternalEqualityComparator<Meta>;
/**
* Additional value that can be used for comparisons.
*/
meta: Meta;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
readonly strict: boolean;
}
export interface CircularState<Meta> extends State<Meta> {
readonly cache: Cache<any, any>;
}
export interface DefaultState<Meta> extends State<Meta> {
readonly cache: undefined;
}
export interface Dictionary<Value = any> {
[key: string | symbol]: Value;
$$typeof?: any;
}
export interface ComparatorConfig<Meta> {
/**
* Whether the arrays passed are equal in value. In strict mode, this includes
* additional properties added to the array.
*/
areArraysEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the dates passed are equal in value.
*/
areDatesEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the maps passed are equal in value. In strict mode, this includes
* additional properties added to the map.
*/
areMapsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the objects passed are equal in value. In strict mode, this includes
* non-enumerable properties added to the map, as well as symbol properties.
*/
areObjectsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the primitive wrappers passed are equal in value.
*/
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the regexps passed are equal in value.
*/
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the sets passed are equal in value. In strict mode, this includes
* additional properties added to the set.
*/
areSetsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the typed arrays passed are equal in value. In strict mode, this includes
* additional properties added to the typed array.
*/
areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
}
export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
export type CreateState<Meta> = () => {
cache?: Cache<any, any> | undefined;
meta?: Meta;
};
export type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
export type PrimitiveWrapper = Boolean | Number | String;
/**
* Type which encompasses possible instances of TypedArray
* classes.
*
* **NOTE**: This does not include `BigInt64Array` and
* `BitUint64Array` because those are part of ES2020 and
* not supported by certain TS configurations. If using
* either in `areTypedArraysEqual`, you can cast the
* instance as `TypedArray` and it will work as expected,
* because runtime checks will still work for those classes.
*/
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
export interface CustomEqualCreatorOptions<Meta> {
/**
* Whether circular references should be supported. It causes the
* comparison to be slower, but for objects that have circular references
* it is required to avoid stack overflows.
*/
circular?: boolean;
/**
* Create a custom configuration of type-specific equality comparators.
* This receives the default configuration, which allows either replacement
* or supersetting of the default methods.
*/
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
/**
* Create a custom internal comparator, which is used as an override to the
* default entry point for nested value equality comparisons. This is often
* used for doing custom logic for specific types (such as handling a specific
* class instance differently than other objects) or to incorporate `meta` in
* the comparison. See the recipes for examples.
*/
createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
/**
* Create a custom `state` object passed between the methods. This allows for
* custom `cache` and/or `meta` values to be used.
*/
createState?: CreateState<Meta>;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
strict?: boolean;
}

24
node_modules/fast-equals/dist/umd/types/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { AnyEqualityComparator, Dictionary, State, TypeEqualityComparator } from './internalTypes';
/**
* Combine two comparators into a single comparators.
*/
export declare function combineComparators<Meta>(comparatorA: AnyEqualityComparator<Meta>, comparatorB: AnyEqualityComparator<Meta>): <A, B>(a: A, b: B, state: State<Meta>) => boolean;
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
export declare function createIsCircular<AreItemsEqual extends TypeEqualityComparator<any, any>>(areItemsEqual: AreItemsEqual): AreItemsEqual;
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
export declare function getStrictProperties(object: Dictionary): Array<string | symbol>;
/**
* Whether the object contains the property passed as an own property.
*/
export declare const hasOwn: (o: object, v: PropertyKey) => boolean;
/**
* Whether the values passed are strictly equal or both NaN.
*/
export declare function sameValueZeroEqual(a: any, b: any): boolean;

54
node_modules/fast-equals/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import type { CustomEqualCreatorOptions } from './src/internalTypes';
export * from './src/internalTypes';
/**
* Whether the values passed are strictly equal or both NaN.
*/
export declare const sameValueZeroEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value.
*/
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value.
*/
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that cannot polyfill for modern features expected by
* `fast-equals`, such as `WeakMap` or `RegExp.prototype.flags`.
*/
export declare function createCustomEqual<Meta = undefined>(
options?: CustomEqualCreatorOptions<Meta>,
): <A, B>(a: A, b: B) => boolean;

113
node_modules/fast-equals/package.json generated vendored Normal file
View File

@@ -0,0 +1,113 @@
{
"author": "tony_quetano@planttheidea.com",
"browser": "dist/umd/index.js",
"bugs": {
"url": "https://github.com/planttheidea/fast-equals/issues"
},
"description": "A blazing fast equality comparison, either shallow or deep",
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/plugin-typescript": "^11.0.0",
"@types/jest": "^29.5.0",
"@types/lodash": "^4.14.184",
"@types/node": "^18.15.3",
"@types/ramda": "^0.28.23",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"decircularize": "^1.0.0",
"deep-eql": "^4.1.0",
"deep-equal": "^2.0.5",
"eslint": "^8.36.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-webpack-plugin": "^4.0.0",
"fast-deep-equal": "^3.1.3",
"html-webpack-plugin": "^5.5.0",
"in-publish": "^2.0.0",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"jest-expect-message": "^1.1.3",
"lodash": "^4.17.21",
"nano-equal": "^2.0.2",
"prettier": "^2.8.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-fast-compare": "^3.2.1",
"release-it": "^15.9.0",
"rollup": "^3.19.1",
"shallow-equal-fuzzy": "^0.0.2",
"tinybench": "^2.4.0",
"ts-jest": "^29.0.3",
"ts-loader": "^9.4.2",
"typescript": "^4.9.5",
"underscore": "^1.13.4",
"webpack": "^5.76.2",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.13.0"
},
"engines": {
"node": ">=6.0.0"
},
"exports": {
".": {
"import": {
"types": "./dist/esm/types/index.d.ts",
"default": "./dist/esm/index.mjs"
},
"require": {
"types": "./dist/cjs/types/index.d.ts",
"default": "./dist/cjs/index.cjs"
},
"default": {
"types": "./dist/umd/types/index.d.ts",
"default": "./dist/umd/index.js"
}
}
},
"homepage": "https://github.com/planttheidea/fast-equals#readme",
"keywords": [
"fast",
"equal",
"equals",
"deep-equal",
"equivalent"
],
"license": "MIT",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.mjs",
"name": "fast-equals",
"repository": {
"type": "git",
"url": "git+https://github.com/planttheidea/fast-equals.git"
},
"scripts": {
"benchmark": "npm run build:esm && node benchmark/index.js",
"build": "npm run build:esm && npm run build:cjs && npm run build:umd && npm run build:min",
"build:cjs": "rimraf dist/cjs && NODE_ENV=production rollup -c build/rollup/config.cjs.js && tsc -p ./build/tsconfig/cjs.json",
"build:esm": "rimraf dist/esm && NODE_ENV=production rollup -c build/rollup/config.esm.js && tsc -p ./build/tsconfig/esm.json",
"build:min": "rimraf dist/min && NODE_ENV=production rollup -c build/rollup/config.min.js && tsc -p ./build/tsconfig/min.json",
"build:umd": "rimraf dist/umd && NODE_ENV=production rollup -c build/rollup/config.umd.js && tsc -p ./build/tsconfig/umd.json",
"dev": "NODE_ENV=development webpack serve --progress --config=build/webpack.config.js",
"dist": "rimraf dist && npm run build",
"format": "prettier **/*.ts --write",
"lint": "eslint src/*.ts",
"lint:fix": "npm run lint -- --fix",
"start": "npm run dev",
"prepublish": "if in-publish; then npm run prepublish:compile; fi",
"release": "release-it",
"release:beta": "release-it --config=.release-it.beta.json",
"release:scripts": "npm run typecheck && npm run lint && npm run test && npm run dist",
"test": "NODE_PATH=. jest",
"test:coverage": "rimraf coverage && npm test -- --coverage",
"test:watch": "npm test -- --watch",
"typecheck": "tsc --noEmit"
},
"sideEffects": false,
"type": "module",
"types": "./index.d.ts",
"version": "5.0.1"
}

View File

@@ -0,0 +1,26 @@
# Explicit property check
Sometimes it is necessary to squeeze every once of performance out of your runtime code, and deep equality checks can be a bottleneck. When this is occurs, it can be advantageous to build a custom comparison that allows for highly specific equality checks.
An example where you know the shape of the objects being passed in, where the `foo` property is a simple primitive and the `bar` property is a nested object:
```ts
import { createCustomEqual } from 'fast-equals';
import type { TypeEqualityComparator } from 'fast-equals';
interface SpecialObject {
foo: string;
bar: {
baz: number;
};
}
const areObjectsEqual: TypeEqualityComparator<SpecialObject, undefined> = (
a,
b,
) => a.foo === b.foo && a.bar.baz === b.bar.baz;
const isSpecialObjectEqual = createCustomEqual({
createCustomConfig: () => ({ areObjectsEqual }),
});
```

View File

@@ -0,0 +1,75 @@
# Legacy environment support for circular equal comparators
Starting in `4.x.x`, `WeakMap` is expected to be available in the environment. All modern browsers support this global object, however there may be situations where a legacy environmental support is required (example: IE11). If you need to support such an environment and polyfilling is not an option, creating a custom comparator that uses a custom cache implementation with the same contract is a simple solution.
```ts
import { createCustomEqual, sameValueZeroEqual } from 'fast-equals';
import type { Cache } from 'fast-equals';
function getCache(): Cache<any, any> {
const entries: Array<[object, any]> = [];
return {
delete(key) {
for (let index = 0; index < entries.length; ++index) {
if (entries[index][0] === key) {
entries.splice(index, 1);
return true;
}
}
return false;
},
get(key) {
for (let index = 0; index < entries.length; ++index) {
if (entries[index][0] === key) {
return entries[index][1];
}
}
},
set(key, value) {
for (let index = 0; index < entries.length; ++index) {
if (entries[index][0] === key) {
entries[index][1] = value;
return this;
}
}
entries.push([key, value]);
return this;
},
};
}
interface Meta {
customMethod(): void;
customValue: string;
}
const meta = {
customMethod() {
console.log('hello!');
},
customValue: 'goodbye',
};
const circularDeepEqual = createCustomEqual<Cache>({
circular: true,
createState: () => ({
cache: getCache(),
meta,
}),
});
const circularShallowEqual = createCustomEqual<Cache>({
circular: true,
comparator: sameValueZeroEqual,
createState: () => ({
cache: getCache(),
meta,
}),
});
```

View File

@@ -0,0 +1,24 @@
# Legacy environment support for `RegExp` comparators
Starting in `4.x.x`, `RegExp.prototype.flags` is expected to be available in the environment. All modern browsers support this feature, however there may be situations where a legacy environmental support is required (example: IE11). If you need to support such an environment and polyfilling is not an option, creating a custom comparator that uses a more verbose comparison of all possible flags is a simple solution.
```ts
import { createCustomEqual, sameValueZeroEqual } from 'deep-Equals';
const areRegExpsEqual = (a: RegExp, b: RegExp) =>
a.source === b.source &&
a.global === b.global &&
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline &&
a.unicode === b.unicode &&
a.sticky === b.sticky &&
a.lastIndex === b.lastIndex;
const deepEqual = createCustomEqual({
createCustomConfig: () => ({ areRegExpsEqual }),
});
const shallowEqual = createCustomEqual({
comparator: sameValueZero,
createCustomConfig: () => ({ areRegExpsEqual }),
});
```

View File

@@ -0,0 +1,48 @@
# Non-standard properties
Sometimes, objects require a comparison that extend beyond its own keys, or even its own properties or symbols. Using a custom object comparator with `createCustomEqual` allows these kinds of comparisons.
```ts
import { createCustomEqual } from 'fast-equals';
import type { TypeEqualityComparator } from 'fast-equals';
type AreObjectsEqual = TypeEqualityComparator<Record<any, any>, undefined>;
class HiddenProperty {
visible: boolean;
#hidden: string;
constructor(value: string) {
this.visible = true;
this.#hidden = value;
}
get hidden() {
return this.#hidden;
}
}
function createAreObjectsEqual(
areObjectsEqual: AreObjectsEqual,
): AreObjectsEqual {
return function (a, b, state) {
if (!areObjectsEqual(a, b, state)) {
return false;
}
const aInstance = a instanceof HiddenProperty;
const bInstance = b instanceof HiddenProperty;
if (aInstance || bInstance) {
return aInstance && bInstance && a.hidden === b.hidden;
}
return true;
};
}
const deepEqual = createCustomEqual({
createCustomConfig: ({ areObjectsEqual }) =>
createAreObjectsEqual(areObjectsEqual),
});
```

View File

@@ -0,0 +1,20 @@
# Using `meta` in comparison
Sometimes a "pure" equality between two objects is insufficient, because the comparison relies on some external state. While these kinds of scenarios should generally be avoided, it is possible to handle them with a custom internal comparator that checks `meta` values.
```ts
import { createCustomEqual } from 'fast-equals';
interface Meta {
value: string;
}
const meta: Meta = { value: 'baz' };
const deepEqual = createCustomEqual<Meta>({
createInternalComparator:
(compare) => (a, b, _keyA, _keyB, _parentA, _parentB, state) =>
compare(a, b, state) || a === state.meta.value || b === state.meta.value,
createState: () => ({ meta }),
});
```

316
node_modules/fast-equals/src/comparator.ts generated vendored Normal file
View File

@@ -0,0 +1,316 @@
import {
areArraysEqual as areArraysEqualDefault,
areDatesEqual as areDatesEqualDefault,
areMapsEqual as areMapsEqualDefault,
areObjectsEqual as areObjectsEqualDefault,
areObjectsEqualStrict as areObjectsEqualStrictDefault,
arePrimitiveWrappersEqual as arePrimitiveWrappersEqualDefault,
areRegExpsEqual as areRegExpsEqualDefault,
areSetsEqual as areSetsEqualDefault,
areTypedArraysEqual,
} from './equals';
import { combineComparators, createIsCircular } from './utils';
import type {
ComparatorConfig,
CreateState,
CustomEqualCreatorOptions,
EqualityComparator,
InternalEqualityComparator,
State,
} from './internalTypes';
const ARGUMENTS_TAG = '[object Arguments]';
const BOOLEAN_TAG = '[object Boolean]';
const DATE_TAG = '[object Date]';
const MAP_TAG = '[object Map]';
const NUMBER_TAG = '[object Number]';
const OBJECT_TAG = '[object Object]';
const REG_EXP_TAG = '[object RegExp]';
const SET_TAG = '[object Set]';
const STRING_TAG = '[object String]';
const { isArray } = Array;
const isTypedArray =
typeof ArrayBuffer === 'function' && ArrayBuffer.isView
? ArrayBuffer.isView
: null;
const { assign } = Object;
const getTag = Object.prototype.toString.call.bind(
Object.prototype.toString,
) as (a: object) => string;
interface CreateIsEqualOptions<Meta> {
circular: boolean;
comparator: EqualityComparator<Meta>;
createState: CreateState<Meta> | undefined;
equals: InternalEqualityComparator<Meta>;
strict: boolean;
}
/**
* Create a comparator method based on the type-specific equality comparators passed.
*/
export function createEqualityComparator<Meta>({
areArraysEqual,
areDatesEqual,
areMapsEqual,
areObjectsEqual,
arePrimitiveWrappersEqual,
areRegExpsEqual,
areSetsEqual,
areTypedArraysEqual,
}: ComparatorConfig<Meta>): EqualityComparator<Meta> {
/**
* compare the value of the two objects and return true if they are equivalent in values
*/
return function comparator(a: any, b: any, state: State<Meta>): boolean {
// If the items are strictly equal, no need to do a value comparison.
if (a === b) {
return true;
}
// If the items are not non-nullish objects, then the only possibility
// of them being equal but not strictly is if they are both `NaN`. Since
// `NaN` is uniquely not equal to itself, we can use self-comparison of
// both objects, which is faster than `isNaN()`.
if (
a == null ||
b == null ||
typeof a !== 'object' ||
typeof b !== 'object'
) {
return a !== a && b !== b;
}
const constructor = a.constructor;
// Checks are listed in order of commonality of use-case:
// 1. Common complex object types (plain object, array)
// 2. Common data values (date, regexp)
// 3. Less-common complex object types (map, set)
// 4. Less-common data values (promise, primitive wrappers)
// Inherently this is both subjective and assumptive, however
// when reviewing comparable libraries in the wild this order
// appears to be generally consistent.
// Constructors should match, otherwise there is potential for false positives
// between class and subclass or custom object and POJO.
if (constructor !== b.constructor) {
return false;
}
// `isPlainObject` only checks against the object's own realm. Cross-realm
// comparisons are rare, and will be handled in the ultimate fallback, so
// we can avoid capturing the string tag.
if (constructor === Object) {
return areObjectsEqual(a, b, state);
}
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
// the string tag or doing an `instanceof` check.
if (isArray(a)) {
return areArraysEqual(a, b, state);
}
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid
// capturing the string tag or comparing against all possible constructors.
if (isTypedArray != null && isTypedArray(a)) {
return areTypedArraysEqual(a, b, state);
}
// Try to fast-path equality checks for other complex object types in the
// same realm to avoid capturing the string tag. Strict equality is used
// instead of `instanceof` because it is more performant for the common
// use-case. If someone is subclassing a native class, it will be handled
// with the string tag comparison.
if (constructor === Date) {
return areDatesEqual(a, b, state);
}
if (constructor === RegExp) {
return areRegExpsEqual(a, b, state);
}
if (constructor === Map) {
return areMapsEqual(a, b, state);
}
if (constructor === Set) {
return areSetsEqual(a, b, state);
}
// Since this is a custom object, capture the string tag to determing its type.
// This is reasonably performant in modern environments like v8 and SpiderMonkey.
const tag = getTag(a);
if (tag === DATE_TAG) {
return areDatesEqual(a, b, state);
}
if (tag === REG_EXP_TAG) {
return areRegExpsEqual(a, b, state);
}
if (tag === MAP_TAG) {
return areMapsEqual(a, b, state);
}
if (tag === SET_TAG) {
return areSetsEqual(a, b, state);
}
if (tag === OBJECT_TAG) {
// The exception for value comparison is custom `Promise`-like class instances. These should
// be treated the same as standard `Promise` objects, which means strict equality, and if
// it reaches this point then that strict equality comparison has already failed.
return (
typeof a.then !== 'function' &&
typeof b.then !== 'function' &&
areObjectsEqual(a, b, state)
);
}
// If an arguments tag, it should be treated as a standard object.
if (tag === ARGUMENTS_TAG) {
return areObjectsEqual(a, b, state);
}
// As the penultimate fallback, check if the values passed are primitive wrappers. This
// is very rare in modern JS, which is why it is deprioritized compared to all other object
// types.
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
return arePrimitiveWrappersEqual(a, b, state);
}
// If not matching any tags that require a specific type of comparison, then we hard-code false because
// the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
// - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
// comparison that can be made.
// - For types that can be introspected, but rarely have requirements to be compared
// (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common
// use-cases (may be included in a future release, if requested enough).
// - For types that can be introspected but do not have an objective definition of what
// equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
// In all cases, these decisions should be reevaluated based on changes to the language and
// common development practices.
return false;
};
}
/**
* Create the configuration object used for building comparators.
*/
export function createEqualityComparatorConfig<Meta>({
circular,
createCustomConfig,
strict,
}: CustomEqualCreatorOptions<Meta>): ComparatorConfig<Meta> {
let config = {
areArraysEqual: strict
? areObjectsEqualStrictDefault
: areArraysEqualDefault,
areDatesEqual: areDatesEqualDefault,
areMapsEqual: strict
? combineComparators(areMapsEqualDefault, areObjectsEqualStrictDefault)
: areMapsEqualDefault,
areObjectsEqual: strict
? areObjectsEqualStrictDefault
: areObjectsEqualDefault,
arePrimitiveWrappersEqual: arePrimitiveWrappersEqualDefault,
areRegExpsEqual: areRegExpsEqualDefault,
areSetsEqual: strict
? combineComparators(areSetsEqualDefault, areObjectsEqualStrictDefault)
: areSetsEqualDefault,
areTypedArraysEqual: strict
? areObjectsEqualStrictDefault
: areTypedArraysEqual,
};
if (createCustomConfig) {
config = assign({}, config, createCustomConfig(config));
}
if (circular) {
const areArraysEqual = createIsCircular(config.areArraysEqual);
const areMapsEqual = createIsCircular(config.areMapsEqual);
const areObjectsEqual = createIsCircular(config.areObjectsEqual);
const areSetsEqual = createIsCircular(config.areSetsEqual);
config = assign({}, config, {
areArraysEqual,
areMapsEqual,
areObjectsEqual,
areSetsEqual,
});
}
return config;
}
/**
* Default equality comparator pass-through, used as the standard `isEqual` creator for
* use inside the built comparator.
*/
export function createInternalEqualityComparator<Meta>(
compare: EqualityComparator<Meta>,
): InternalEqualityComparator<Meta> {
return function (
a: any,
b: any,
_indexOrKeyA: any,
_indexOrKeyB: any,
_parentA: any,
_parentB: any,
state: State<Meta>,
) {
return compare(a, b, state);
};
}
/**
* Create the `isEqual` function used by the consuming application.
*/
export function createIsEqual<Meta>({
circular,
comparator,
createState,
equals,
strict,
}: CreateIsEqualOptions<Meta>) {
if (createState) {
return function isEqual<A, B>(a: A, b: B): boolean {
const { cache = circular ? new WeakMap() : undefined, meta } =
createState!();
return comparator(a, b, {
cache,
equals,
meta,
strict,
} as State<Meta>);
};
}
if (circular) {
return function isEqual<A, B>(a: A, b: B): boolean {
return comparator(a, b, {
cache: new WeakMap(),
equals,
meta: undefined as Meta,
strict,
} as State<Meta>);
};
}
const state = {
cache: undefined,
equals,
meta: undefined,
strict,
} as State<Meta>;
return function isEqual<A, B>(a: A, b: B): boolean {
return comparator(a, b, state);
};
}

300
node_modules/fast-equals/src/equals.ts generated vendored Normal file
View File

@@ -0,0 +1,300 @@
import { getStrictProperties, hasOwn, sameValueZeroEqual } from './utils';
import type {
Dictionary,
PrimitiveWrapper,
State,
TypedArray,
} from './internalTypes';
const OWNER = '_owner';
const { getOwnPropertyDescriptor, keys } = Object;
/**
* Whether the arrays are equal in value.
*/
export function areArraysEqual(a: any[], b: any[], state: State<any>) {
let index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (!state.equals(a[index], b[index], index, index, a, b, state)) {
return false;
}
}
return true;
}
/**
* Whether the dates passed are equal in value.
*/
export function areDatesEqual(a: Date, b: Date): boolean {
return sameValueZeroEqual(a.getTime(), b.getTime());
}
/**
* Whether the `Map`s are equal in value.
*/
export function areMapsEqual(
a: Map<any, any>,
b: Map<any, any>,
state: State<any>,
): boolean {
if (a.size !== b.size) {
return false;
}
const matchedIndices: Record<number, true> = {};
const aIterable = a.entries();
let index = 0;
let aResult: IteratorResult<[any, any]>;
let bResult: IteratorResult<[any, any]>;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
const bIterable = b.entries();
let hasMatch = false;
let matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
const [aKey, aValue] = aResult.value;
const [bKey, bValue] = bResult.value;
if (
!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch =
state.equals(aKey, bKey, index, matchIndex, a, b, state) &&
state.equals(aValue, bValue, aKey, bKey, a, b, state))
) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
index++;
}
return true;
}
/**
* Whether the objects are equal in value.
*/
export function areObjectsEqual(
a: Dictionary,
b: Dictionary,
state: State<any>,
): boolean {
const properties = keys(a);
let index = properties.length;
if (keys(b).length !== index) {
return false;
}
let property: string;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index]!;
if (
property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof
) {
return false;
}
if (
!hasOwn(b, property) ||
!state.equals(a[property], b[property], property, property, a, b, state)
) {
return false;
}
}
return true;
}
/**
* Whether the objects are equal in value with strict property checking.
*/
export function areObjectsEqualStrict(
a: Dictionary,
b: Dictionary,
state: State<any>,
): boolean {
const properties = getStrictProperties(a);
let index = properties.length;
if (getStrictProperties(b).length !== index) {
return false;
}
let property: string | symbol;
let descriptorA: ReturnType<typeof getOwnPropertyDescriptor>;
let descriptorB: ReturnType<typeof getOwnPropertyDescriptor>;
// Decrementing `while` showed faster results than either incrementing or
// decrementing `for` loop and than an incrementing `while` loop. Declarative
// methods like `some` / `every` were not used to avoid incurring the garbage
// cost of anonymous callbacks.
while (index-- > 0) {
property = properties[index]!;
if (
property === OWNER &&
(a.$$typeof || b.$$typeof) &&
a.$$typeof !== b.$$typeof
) {
return false;
}
if (!hasOwn(b, property)) {
return false;
}
if (
!state.equals(a[property], b[property], property, property, a, b, state)
) {
return false;
}
descriptorA = getOwnPropertyDescriptor(a, property);
descriptorB = getOwnPropertyDescriptor(b, property);
if (
(descriptorA || descriptorB) &&
(!descriptorA ||
!descriptorB ||
descriptorA.configurable !== descriptorB.configurable ||
descriptorA.enumerable !== descriptorB.enumerable ||
descriptorA.writable !== descriptorB.writable)
) {
return false;
}
}
return true;
}
/**
* Whether the primitive wrappers passed are equal in value.
*/
export function arePrimitiveWrappersEqual(
a: PrimitiveWrapper,
b: PrimitiveWrapper,
): boolean {
return sameValueZeroEqual(a.valueOf(), b.valueOf());
}
/**
* Whether the regexps passed are equal in value.
*/
export function areRegExpsEqual(a: RegExp, b: RegExp): boolean {
return a.source === b.source && a.flags === b.flags;
}
/**
* Whether the `Set`s are equal in value.
*/
export function areSetsEqual(
a: Set<any>,
b: Set<any>,
state: State<any>,
): boolean {
if (a.size !== b.size) {
return false;
}
const matchedIndices: Record<number, true> = {};
const aIterable = a.values();
let aResult: IteratorResult<any>;
let bResult: IteratorResult<any>;
while ((aResult = aIterable.next())) {
if (aResult.done) {
break;
}
const bIterable = b.values();
let hasMatch = false;
let matchIndex = 0;
while ((bResult = bIterable.next())) {
if (bResult.done) {
break;
}
if (
!hasMatch &&
!matchedIndices[matchIndex] &&
(hasMatch = state.equals(
aResult.value,
bResult.value,
aResult.value,
bResult.value,
a,
b,
state,
))
) {
matchedIndices[matchIndex] = true;
}
matchIndex++;
}
if (!hasMatch) {
return false;
}
}
return true;
}
/**
* Whether the TypedArray instances are equal in value.
*/
export function areTypedArraysEqual(a: TypedArray, b: TypedArray) {
let index = a.length;
if (b.length !== index) {
return false;
}
while (index-- > 0) {
if (a[index] !== b[index]) {
return false;
}
}
return true;
}

95
node_modules/fast-equals/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,95 @@
import {
createEqualityComparatorConfig,
createEqualityComparator,
createInternalEqualityComparator,
createIsEqual,
} from './comparator';
import type { CustomEqualCreatorOptions } from './internalTypes';
import { sameValueZeroEqual } from './utils';
export { sameValueZeroEqual };
export * from './internalTypes';
/**
* Whether the items passed are deeply-equal in value.
*/
export const deepEqual = createCustomEqual();
/**
* Whether the items passed are deeply-equal in value based on strict comparison.
*/
export const strictDeepEqual = createCustomEqual({ strict: true });
/**
* Whether the items passed are deeply-equal in value, including circular references.
*/
export const circularDeepEqual = createCustomEqual({ circular: true });
/**
* Whether the items passed are deeply-equal in value, including circular references,
* based on strict comparison.
*/
export const strictCircularDeepEqual = createCustomEqual({
circular: true,
strict: true,
});
/**
* Whether the items passed are shallowly-equal in value.
*/
export const shallowEqual = createCustomEqual({
createInternalComparator: () => sameValueZeroEqual,
});
/**
* Whether the items passed are shallowly-equal in value based on strict comparison
*/
export const strictShallowEqual = createCustomEqual({
strict: true,
createInternalComparator: () => sameValueZeroEqual,
});
/**
* Whether the items passed are shallowly-equal in value, including circular references.
*/
export const circularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: () => sameValueZeroEqual,
});
/**
* Whether the items passed are shallowly-equal in value, including circular references,
* based on strict comparison.
*/
export const strictCircularShallowEqual = createCustomEqual({
circular: true,
createInternalComparator: () => sameValueZeroEqual,
strict: true,
});
/**
* Create a custom equality comparison method.
*
* This can be done to create very targeted comparisons in extreme hot-path scenarios
* where the standard methods are not performant enough, but can also be used to provide
* support for legacy environments that do not support expected features like
* `RegExp.prototype.flags` out of the box.
*/
export function createCustomEqual<Meta = undefined>(
options: CustomEqualCreatorOptions<Meta> = {},
) {
const {
circular = false,
createInternalComparator: createCustomInternalComparator,
createState,
strict = false,
} = options;
const config = createEqualityComparatorConfig<Meta>(options);
const comparator = createEqualityComparator(config);
const equals = createCustomInternalComparator
? createCustomInternalComparator(comparator)
: createInternalEqualityComparator(comparator);
return createIsEqual({ circular, comparator, createState, equals, strict });
}

185
node_modules/fast-equals/src/internalTypes.ts generated vendored Normal file
View File

@@ -0,0 +1,185 @@
/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {
delete(key: Key): boolean;
get(key: Key): Value | undefined;
set(key: Key, value: any): any;
}
export interface State<Meta> {
/**
* Cache used to identify circular references
*/
readonly cache: Cache<any, any> | undefined;
/**
* Method used to determine equality of nested value.
*/
readonly equals: InternalEqualityComparator<Meta>;
/**
* Additional value that can be used for comparisons.
*/
meta: Meta;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
readonly strict: boolean;
}
export interface CircularState<Meta> extends State<Meta> {
readonly cache: Cache<any, any>;
}
export interface DefaultState<Meta> extends State<Meta> {
readonly cache: undefined;
}
export interface Dictionary<Value = any> {
[key: string | symbol]: Value;
$$typeof?: any;
}
export interface ComparatorConfig<Meta> {
/**
* Whether the arrays passed are equal in value. In strict mode, this includes
* additional properties added to the array.
*/
areArraysEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the dates passed are equal in value.
*/
areDatesEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the maps passed are equal in value. In strict mode, this includes
* additional properties added to the map.
*/
areMapsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the objects passed are equal in value. In strict mode, this includes
* non-enumerable properties added to the map, as well as symbol properties.
*/
areObjectsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the primitive wrappers passed are equal in value.
*/
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the regexps passed are equal in value.
*/
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the sets passed are equal in value. In strict mode, this includes
* additional properties added to the set.
*/
areSetsEqual: TypeEqualityComparator<any, Meta>;
/**
* Whether the typed arrays passed are equal in value. In strict mode, this includes
* additional properties added to the typed array.
*/
areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
}
export type CreateCustomComparatorConfig<Meta> = (
config: ComparatorConfig<Meta>,
) => Partial<ComparatorConfig<Meta>>;
export type CreateState<Meta> = () => {
cache?: Cache<any, any> | undefined;
meta?: Meta;
};
export type EqualityComparator<Meta> = <A, B>(
a: A,
b: B,
state: State<Meta>,
) => boolean;
export type AnyEqualityComparator<Meta> = (
a: any,
b: any,
state: State<Meta>,
) => boolean;
export type EqualityComparatorCreator<Meta> = (
fn: EqualityComparator<Meta>,
) => InternalEqualityComparator<Meta>;
export type InternalEqualityComparator<Meta> = (
a: any,
b: any,
indexOrKeyA: any,
indexOrKeyB: any,
parentA: any,
parentB: any,
state: State<Meta>,
) => boolean;
// We explicitly check for primitive wrapper types
// eslint-disable-next-line @typescript-eslint/ban-types
export type PrimitiveWrapper = Boolean | Number | String;
/**
* Type which encompasses possible instances of TypedArray
* classes.
*
* **NOTE**: This does not include `BigInt64Array` and
* `BitUint64Array` because those are part of ES2020 and
* not supported by certain TS configurations. If using
* either in `areTypedArraysEqual`, you can cast the
* instance as `TypedArray` and it will work as expected,
* because runtime checks will still work for those classes.
*/
export type TypedArray =
| Float32Array
| Float64Array
| Int8Array
| Int16Array
| Int32Array
| Uint16Array
| Uint32Array
| Uint8Array
| Uint8ClampedArray;
export type TypeEqualityComparator<Type, Meta = undefined> = (
a: Type,
b: Type,
state: State<Meta>,
) => boolean;
export interface CustomEqualCreatorOptions<Meta> {
/**
* Whether circular references should be supported. It causes the
* comparison to be slower, but for objects that have circular references
* it is required to avoid stack overflows.
*/
circular?: boolean;
/**
* Create a custom configuration of type-specific equality comparators.
* This receives the default configuration, which allows either replacement
* or supersetting of the default methods.
*/
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
/**
* Create a custom internal comparator, which is used as an override to the
* default entry point for nested value equality comparisons. This is often
* used for doing custom logic for specific types (such as handling a specific
* class instance differently than other objects) or to incorporate `meta` in
* the comparison. See the recipes for examples.
*/
createInternalComparator?: (
compare: EqualityComparator<Meta>,
) => InternalEqualityComparator<Meta>;
/**
* Create a custom `state` object passed between the methods. This allows for
* custom `cache` and/or `meta` values to be used.
*/
createState?: CreateState<Meta>;
/**
* Whether the equality comparison is strict, meaning it matches
* all properties (including symbols and non-enumerable properties)
* with equal shape of descriptors.
*/
strict?: boolean;
}

88
node_modules/fast-equals/src/utils.ts generated vendored Normal file
View File

@@ -0,0 +1,88 @@
import {
AnyEqualityComparator,
Cache,
CircularState,
Dictionary,
State,
TypeEqualityComparator,
} from './internalTypes';
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
const { hasOwnProperty } = Object.prototype;
/**
* Combine two comparators into a single comparators.
*/
export function combineComparators<Meta>(
comparatorA: AnyEqualityComparator<Meta>,
comparatorB: AnyEqualityComparator<Meta>,
) {
return function isEqual<A, B>(a: A, b: B, state: State<Meta>) {
return comparatorA(a, b, state) && comparatorB(a, b, state);
};
}
/**
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
* for circular references to be safely included in the comparison without creating
* stack overflows.
*/
export function createIsCircular<
AreItemsEqual extends TypeEqualityComparator<any, any>,
>(areItemsEqual: AreItemsEqual): AreItemsEqual {
return function isCircular(
a: any,
b: any,
state: CircularState<Cache<any, any>>,
) {
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
return areItemsEqual(a, b, state);
}
const { cache } = state;
const cachedA = cache.get(a);
const cachedB = cache.get(b);
if (cachedA && cachedB) {
return cachedA === b && cachedB === a;
}
cache.set(a, b);
cache.set(b, a);
const result = areItemsEqual(a, b, state);
cache.delete(a);
cache.delete(b);
return result;
} as AreItemsEqual;
}
/**
* Get the properties to strictly examine, which include both own properties that are
* not enumerable and symbol properties.
*/
export function getStrictProperties(
object: Dictionary,
): Array<string | symbol> {
return (getOwnPropertyNames(object) as Array<string | symbol>).concat(
getOwnPropertySymbols(object),
);
}
/**
* Whether the object contains the property passed as an own property.
*/
export const hasOwn =
Object.hasOwn ||
((object: Dictionary, property: number | string | symbol) =>
hasOwnProperty.call(object, property));
/**
* Whether the values passed are strictly equal or both NaN.
*/
export function sameValueZeroEqual(a: any, b: any): boolean {
return a || b ? a === b : a === b || (a !== a && b !== b);
}