Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fast-equals

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fast-equals - npm Package Compare versions

Comparing version 5.0.0-beta.6 to 5.0.0

4

CHANGELOG.md

@@ -27,2 +27,6 @@ # fast-equals CHANGELOG

#### 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

@@ -29,0 +33,0 @@

@@ -0,1 +1,5 @@

/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {

@@ -7,5 +11,19 @@ delete(key: Key): boolean;

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;

@@ -24,9 +42,38 @@ }

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>;

@@ -44,10 +91,47 @@ }

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;
}

@@ -0,1 +1,5 @@

/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {

@@ -7,5 +11,19 @@ delete(key: Key): boolean;

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;

@@ -24,9 +42,38 @@ }

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>;

@@ -44,10 +91,47 @@ }

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;
}

@@ -0,1 +1,5 @@

/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {

@@ -7,5 +11,19 @@ delete(key: Key): boolean;

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;

@@ -24,9 +42,38 @@ }

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>;

@@ -44,10 +91,47 @@ }

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;
}

@@ -0,1 +1,5 @@

/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {

@@ -7,5 +11,19 @@ delete(key: Key): boolean;

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;

@@ -24,9 +42,38 @@ }

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>;

@@ -44,10 +91,47 @@ }

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;
}

10

package.json

@@ -16,3 +16,3 @@ {

"@types/lodash": "^4.14.184",
"@types/node": "^18.14.2",
"@types/node": "^18.14.6",
"@types/ramda": "^0.28.23",

@@ -41,6 +41,6 @@ "@types/react": "^18.0.28",

"react-fast-compare": "^3.2.0",
"release-it": "^15.6.1",
"rollup": "^3.17.3",
"release-it": "^15.7.0",
"rollup": "^3.18.0",
"shallow-equal-fuzzy": "^0.0.2",
"tinybench": "^2.3.1",
"tinybench": "^2.4.0",
"ts-jest": "^29.0.3",

@@ -114,3 +114,3 @@ "ts-loader": "^9.4.2",

"types": "./index.d.ts",
"version": "5.0.0-beta.6"
"version": "5.0.0"
}

@@ -168,2 +168,3 @@ # fast-equals

- Checking symbol properties
- Checking non-enumerable properties in object comparisons

@@ -333,3 +334,3 @@ - Checking full descriptor of properties on the object to match

All benchmarks were performed on an i7-8650U Ubuntu Linux laptop with 24GB of memory using NodeJS version `12.19.1`, and are based on averages of running comparisons based deep equality on the following object types:
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:

@@ -345,16 +346,39 @@ - Primitives (`String`, `Number`, `null`, `undefined`)

| | Operations / second |
| -------------------------- | ------------------- |
| **fast-equals** | **153,880** |
| fast-deep-equal | 144,035 |
| react-fast-compare | 130,324 |
| nano-equal | 104,624 |
| **fast-equals (circular)** | **97,610** |
| shallow-equal-fuzzy | 83,946 |
| underscore.isEqual | 47,370 |
| lodash.isEqual | 25,053 |
| deep-eql | 22,146 |
| assert.deepStrictEqual | 532 |
| deep-equal | 209 |
```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):

@@ -361,0 +385,0 @@

@@ -0,1 +1,5 @@

/**
* Cache used to store references to objects, used for circular
* reference checks.
*/
export interface Cache<Key extends object, Value> {

@@ -8,5 +12,19 @@ delete(key: Key): boolean;

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;

@@ -29,9 +47,38 @@ }

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>;

@@ -78,2 +125,13 @@ }

/**
* 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 =

@@ -97,9 +155,35 @@ | Float32Array

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;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc