UNPKG

typedash

Version:

modern, type-safe collection of utility functions

1 lines 30.1 kB
{"version":3,"file":"isEqual-DkBhumG2.cjs","names":["zip","zip","isArray"],"sources":["../src/functions/isEqual/_internal/array/areArraysEqual.ts","../src/functions/isEqual/_internal/createIsCircularTypeEqualityComparator.ts","../src/functions/isEqual/_internal/date/areDatesEqual.ts","../src/functions/isEqual/_internal/date/dateTag.ts","../src/functions/isEqual/_internal/map/areMapsEqual.ts","../src/functions/isEqual/_internal/react/isReactElement.ts","../src/functions/isEqual/_internal/react/reactInternalProperties.ts","../src/functions/isEqual/_internal/object/getObjectProperties.ts","../src/functions/isEqual/_internal/react/areReactElementsEqual.ts","../src/functions/isEqual/_internal/object/areObjectsEqual.ts","../src/functions/isEqual/_internal/primitiveWrappers/arePrimitiveWrappersEqual.ts","../src/functions/isEqual/_internal/regExp/areRegExpsEqual.ts","../src/functions/isEqual/_internal/regExp/regExpTag.ts","../src/functions/isEqual/_internal/set/areSetsEqual.ts","../src/functions/isEqual/_internal/set/setTag.ts","../src/functions/isEqual/_internal/typedArray/areTypedArraysEqual.ts","../src/functions/isEqual/_internal/typedArray/isTypedArray.ts","../src/functions/isEqual/_internal/comparator.ts","../src/functions/isEqual/_internal/createEqualityComparator.ts","../src/functions/isEqual/isEqual.ts"],"sourcesContent":["import { zip } from '../../../zip';\nimport type { Context } from '../types';\n\n/**\n * Whether the arrays are equal in value.\n * @param array1 The first array.\n * @param array2 The second array.\n * @param context The context object.\n * @returns true if the two arrays are equal, false otherwise.\n */\nexport function areArraysEqual(\n array1: readonly unknown[],\n array2: readonly unknown[],\n context: Context\n) {\n if (array1.length !== array2.length) {\n return false;\n }\n\n for (const [index, [element1, element2]] of zip(array1, array2).entries()) {\n if (\n !context.equals(element1, element2, index, index, array1, array2, context)\n ) {\n return false;\n }\n }\n\n return true;\n}\n","import type { Context, TypeEqualityComparator } from './types';\n\n/**\n * Wrap the provided `areItemsEqual` method to manage the circular state, allowing\n * for circular references to be safely included in the comparison without creating\n * stack overflows.\n * @param areItemsEqual The comparator to wrap.\n * @returns A comparator that can handle circular references.\n */\nexport function createIsCircularTypeEqualityComparator<T>(\n areItemsEqual: TypeEqualityComparator<T>\n) {\n return function isCircular(a: T, b: T, context: Context) {\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {\n return areItemsEqual(a, b, context);\n }\n\n const { cache } = context;\n\n const cachedA = cache.get(a);\n const cachedB = cache.get(b);\n\n if (cachedA && cachedB) {\n return cachedA === b && cachedB === a;\n }\n\n cache.set(a, b);\n cache.set(b, a);\n\n const result = areItemsEqual(a, b, context);\n\n cache.delete(a);\n cache.delete(b);\n\n return result;\n };\n}\n","/**\n * Whether the dates passed are equal in value.\n * @param value1 The first date.\n * @param value2 The second date.\n * @returns true if the two dates are equal, false otherwise.\n */\nexport function areDatesEqual(value1: Date, value2: Date): boolean {\n return Object.is(value1.getTime(), value2.getTime());\n}\n","export const DATE_TAG = '[object Date]';\n","import type { Context } from '../types';\n\n/**\n * Whether the `Map`s are equal in value.\n * @param value1 The first `Map`.\n * @param value2 The second `Map`.\n * @param context The context object.\n * @returns true if the two `Map`s are equal, false otherwise.\n */\nexport function areMapsEqual(\n value1: ReadonlyMap<unknown, unknown>,\n value2: ReadonlyMap<unknown, unknown>,\n context: Context\n): boolean {\n if (value1.size !== value2.size) {\n return false;\n }\n\n const matchedIndices: Record<number, true> = {};\n\n let index = 0;\n\n for (const [aKey, aValue] of value1) {\n let hasMatch = false;\n let matchIndex = 0;\n\n for (const [bKey, bValue] of value2) {\n if (\n !hasMatch &&\n !matchedIndices[matchIndex] &&\n // biome-ignore lint/suspicious/noAssignInExpressions: faster and simpler in this case due to the nature of the callsite\n (hasMatch =\n context.equals(\n aKey,\n bKey,\n index,\n matchIndex,\n value1,\n value2,\n context\n ) &&\n context.equals(aValue, bValue, aKey, bKey, value1, value2, context))\n ) {\n matchedIndices[matchIndex] = true;\n }\n\n matchIndex++;\n }\n\n if (!hasMatch) {\n return false;\n }\n\n index++;\n }\n\n return true;\n}\n","/**\n * Check if an object is a React element by examining its $$typeof property.\n * Supports both React 18 and React 19 element types.\n *\n * React <=18: Symbol.for('react.element')\n * React 19: Symbol.for('react.transitional.element')\n */\nexport function isReactElement(obj: unknown): boolean {\n return !!(\n obj &&\n typeof obj === 'object' &&\n obj !== null &&\n '$$typeof' in obj &&\n typeof (obj as { $$typeof: unknown }).$$typeof === 'symbol' &&\n ((obj as { $$typeof: symbol }).$$typeof\n .toString()\n .includes('react.element') ||\n (obj as { $$typeof: symbol }).$$typeof\n .toString()\n .includes('react.transitional.element'))\n );\n}\n","/**\n * React internal properties that should be ignored during equality comparison.\n * These properties can differ between logically equivalent React elements:\n *\n * - _owner: React component that created this element (circular reference)\n * - ref: Reference to DOM node or component instance\n * - _store: Internal React state storage\n * - _debugInfo: React 19 debug information (dev mode)\n * - _debugStack: React 19 debug stack trace (dev mode)\n * - _debugTask: React 19 debug task information (dev mode)\n */\nexport const REACT_INTERNAL_PROPERTIES = new Set([\n '_owner',\n 'ref',\n '_store',\n '_debugInfo',\n '_debugStack',\n '_debugTask',\n]);\n\n/**\n * Check if a property name is a React internal property that should be\n * ignored during equality comparison.\n */\nexport function isReactInternalProperty(\n propertyName: string | symbol\n): boolean {\n // Only string properties can be React internal properties\n return (\n typeof propertyName === 'string' &&\n REACT_INTERNAL_PROPERTIES.has(propertyName)\n );\n}\n","import type { Dictionary } from './Dictionary';\n\n/**\n * Get the properties to strictly examine, which include both own properties that are\n * not enumerable and symbol properties.\n * @param object The object to get the properties for.\n * @returns The properties to strictly examine.\n */\nexport function getObjectProperties(\n object: Dictionary\n): Array<string | symbol> {\n return [\n ...Object.getOwnPropertyNames(object),\n ...Object.getOwnPropertySymbols(object),\n ];\n}\n","import type { Context } from '../types/types';\nimport type { Dictionary } from '../object/Dictionary';\nimport { getObjectProperties } from '../object/getObjectProperties';\nimport { isReactElement } from './isReactElement';\nimport { isReactInternalProperty } from './reactInternalProperties';\n\n/**\n * Compare two React elements for equality.\n *\n * React elements are considered equal if they have the same:\n * - $$typeof (React element symbol)\n * - type (component or tag name)\n * - key\n * - props (deep comparison)\n *\n * Internal React properties like _owner, ref, _store, and debug properties\n * are ignored as they can differ between logically equivalent elements.\n */\nexport function areReactElementsEqual(\n element1: Dictionary,\n element2: Dictionary,\n context: Context\n): boolean {\n // Verify both are React elements\n if (!isReactElement(element1) || !isReactElement(element2)) {\n return false;\n }\n\n // Check $$typeof symbols are identical\n if (element1.$$typeof !== element2.$$typeof) {\n return false;\n }\n\n const properties1 = getObjectProperties(element1);\n const properties2 = getObjectProperties(element2);\n\n // Filter out React internal properties for length comparison\n const semanticProps1 = properties1.filter(\n (prop) => !isReactInternalProperty(prop)\n );\n const semanticProps2 = properties2.filter(\n (prop) => !isReactInternalProperty(prop)\n );\n\n if (semanticProps1.length !== semanticProps2.length) {\n return false;\n }\n\n // Compare only semantic properties\n for (const property of properties1) {\n // Skip React internal properties\n if (isReactInternalProperty(property)) {\n continue;\n }\n\n if (!Object.hasOwn(element2, property)) {\n return false;\n }\n\n if (\n !context.equals(\n element1[property],\n element2[property],\n property,\n property,\n element1,\n element2,\n context\n )\n ) {\n return false;\n }\n }\n\n return true;\n}\n","import { areReactElementsEqual, isReactElement } from '../react';\nimport type { Context } from '../types/types';\n\nimport type { Dictionary } from './Dictionary';\nimport { getObjectProperties } from './getObjectProperties';\n\n/**\n * Whether the objects are equal in value with strict property checking.\n * @param value1 The first object.\n * @param value2 The second object.\n * @param context The context object.\n * @returns true if the two objects are equal, false otherwise.\n */\nexport function areObjectsEqual(\n value1: Dictionary,\n value2: Dictionary,\n context: Context\n): boolean {\n // Delegate to specialized React element comparator if both are React elements\n if (isReactElement(value1) && isReactElement(value2)) {\n return areReactElementsEqual(value1, value2, context);\n }\n\n // If only one is a React element, they're not equal\n if (isReactElement(value1) || isReactElement(value2)) {\n return false;\n }\n\n // Standard object comparison for non-React elements\n const properties = getObjectProperties(value1);\n\n if (getObjectProperties(value2).length !== properties.length) {\n return false;\n }\n\n for (const property of properties) {\n if (!Object.hasOwn(value2, property)) {\n return false;\n }\n\n if (\n !context.equals(\n value1[property],\n value2[property],\n property,\n property,\n value1,\n value2,\n context\n )\n ) {\n return false;\n }\n }\n\n return true;\n}\n","/**\n * Whether the primitive wrappers passed are equal in value.\n * @param value1 The first primitive wrapper.\n * @param value2 The second primitive wrapper.\n * @returns true if the two primitive wrappers are equal, false otherwise.\n */\nexport function arePrimitiveWrappersEqual(\n value1: PrimitiveWrapper,\n value2: PrimitiveWrapper\n): boolean {\n return Object.is(value1.valueOf(), value2.valueOf());\n}\n\nexport type PrimitiveWrapper = boolean | number | string;\n","/**\n * Whether the regexps passed are equal in value.\n * @param value1 The first regexp.\n * @param value2 The second regexp.\n * @returns true if the two regexps are equal, false otherwise.\n */\nexport function areRegExpsEqual(value1: RegExp, value2: RegExp): boolean {\n return value1.source === value2.source && value1.flags === value2.flags;\n}\n","export const REG_EXP_TAG = '[object RegExp]';\n","import type { Context } from '../types';\n\n/**\n * Whether the `Set`s are equal in value.\n * @param set1 The first `Set`.\n * @param set2 The second `Set`.\n * @param context The context object.\n * @returns true if the two `Set`s are equal, false otherwise.\n */\nexport function areSetsEqual(\n set1: ReadonlySet<unknown>,\n set2: ReadonlySet<unknown>,\n context: Context\n): boolean {\n if (set1.size !== set2.size) {\n return false;\n }\n\n const matchedIndices: Record<number, true> = {};\n\n for (const element1 of set1) {\n let hasMatch = false;\n let matchIndex = 0;\n\n for (const element2 of set2) {\n if (\n !hasMatch &&\n !matchedIndices[matchIndex] &&\n // biome-ignore lint/suspicious/noAssignInExpressions: faster and simpler in this case due to the nature of the callsite\n (hasMatch = context.equals(\n element1,\n element2,\n element1,\n element2,\n set1,\n set2,\n context\n ))\n ) {\n matchedIndices[matchIndex] = true;\n }\n\n matchIndex++;\n }\n\n if (!hasMatch) {\n return false;\n }\n }\n\n return true;\n}\n","export const SET_TAG = '[object Set]';\n","import type { TypedArray } from 'type-fest';\n\nimport { zip } from '../../../zip';\n\n/**\n * Whether the TypedArray instances are equal in value.\n * @param array1 The first TypedArray instance.\n * @param array2 The second TypedArray instance.\n * @returns true if the two TypedArray instances are equal, false otherwise.\n */\nexport function areTypedArraysEqual(array1: TypedArray, array2: TypedArray) {\n if (array1.length !== array2.length) {\n return false;\n }\n\n for (const [element1, element2] of zip(array1, array2)) {\n if (element1 !== element2) {\n return false;\n }\n }\n\n return true;\n}\n","export const isTypedArray =\n typeof ArrayBuffer === 'function' && ArrayBuffer.isView\n ? ArrayBuffer.isView\n : null;\n","import { areArraysEqual } from './array';\nimport { createIsCircularTypeEqualityComparator } from './createIsCircularTypeEqualityComparator';\nimport { areDatesEqual } from './date';\nimport { areMapsEqual } from './map';\nimport { areObjectsEqual } from './object';\nimport { arePrimitiveWrappersEqual } from './primitiveWrappers';\nimport { areRegExpsEqual } from './regExp';\nimport { areSetsEqual } from './set';\nimport { areTypedArraysEqual } from './typedArray';\nimport type {\n ComparatorConfig,\n Context,\n EqualityComparator,\n InternalEqualityComparator,\n} from './types';\n\nexport const ARGUMENTS_TAG = '[object Arguments]';\nexport const BOOLEAN_TAG = '[object Boolean]';\nexport const MAP_TAG = '[object Map]';\nexport const NUMBER_TAG = '[object Number]';\nexport const OBJECT_TAG = '[object Object]';\nexport const STRING_TAG = '[object String]';\n\nexport const getTag = Object.prototype.toString.call.bind(\n Object.prototype.toString\n) as (a: object) => string;\n\ninterface CreateIsEqualOptions {\n comparator: EqualityComparator;\n equals: InternalEqualityComparator;\n}\n\n/**\n * Create the configuration object used for building comparators.\n */\nexport function createEqualityComparatorConfig(): ComparatorConfig {\n return {\n areDatesEqual,\n areRegExpsEqual,\n arePrimitiveWrappersEqual,\n areArraysEqual: createIsCircularTypeEqualityComparator(areArraysEqual),\n areMapsEqual: createIsCircularTypeEqualityComparator(areMapsEqual),\n areObjectsEqual: createIsCircularTypeEqualityComparator(areObjectsEqual),\n areSetsEqual: createIsCircularTypeEqualityComparator(areSetsEqual),\n areTypedArraysEqual,\n };\n}\n\n/**\n * Default equality comparator pass-through, used as the standard `isEqual` creator for\n * use inside the built comparator.\n */\nexport function createInternalEqualityComparator(\n compare: EqualityComparator\n): InternalEqualityComparator {\n return function internalEqualityComparator(\n value1: unknown,\n value2: unknown,\n _indexOrKeyA: unknown,\n _indexOrKeyB: unknown,\n _parentA: unknown,\n _parentB: unknown,\n context: Context\n ) {\n return compare(value1, value2, context);\n };\n}\n\n/**\n * Create the `isEqual` function used by the consuming application.\n */\nexport function createIsEqual({ comparator, equals }: CreateIsEqualOptions) {\n return function isEqual<T1, T2>(value1: T1, value2: T2): boolean {\n return comparator(value1, value2, {\n cache: new WeakMap(),\n equals,\n });\n };\n}\n","import type { TypedArray } from 'type-fest';\n\nimport { isArray } from '../../isArray';\n\nimport {\n ARGUMENTS_TAG,\n BOOLEAN_TAG,\n getTag,\n MAP_TAG,\n NUMBER_TAG,\n OBJECT_TAG,\n STRING_TAG,\n} from './comparator';\nimport { DATE_TAG } from './date';\nimport { REG_EXP_TAG } from './regExp';\nimport { SET_TAG } from './set';\nimport { isTypedArray } from './typedArray';\nimport type { ComparatorConfig, Context, EqualityComparator } from './types';\n\n/**\n * Create a comparator method based on the type-specific equality comparators passed.\n * @param root0 The configuration object.\n * @param root0.areArraysEqual The array equality comparator.\n * @param root0.areDatesEqual The date equality comparator.\n * @param root0.areMapsEqual The map equality comparator.\n * @param root0.areObjectsEqual The object equality comparator.\n * @param root0.arePrimitiveWrappersEqual The primitive wrapper equality comparator.\n * @param root0.areRegExpsEqual The regular expression equality comparator.\n * @param root0.areSetsEqual The set equality comparator.\n * @param root0.areTypedArraysEqual The typed array equality comparator.\n * @returns The comparator method.\n */\nexport function createEqualityComparator({\n areArraysEqual,\n areDatesEqual,\n areMapsEqual,\n areObjectsEqual,\n arePrimitiveWrappersEqual,\n areRegExpsEqual,\n areSetsEqual,\n areTypedArraysEqual,\n}: ComparatorConfig): EqualityComparator {\n /**\n * compare the value of the two objects and return true if they are equivalent in values\n * @param value1 the first value to compare\n * @param value2 the second value to compare\n * @param context the context object\n * @returns true if the two values are equivalent in values\n */\n return function comparator(\n // biome-ignore lint/suspicious/noExplicitAny: implicit any is necessary for the comparison\n value1: any,\n // biome-ignore lint/suspicious/noExplicitAny: implicit any is necessary for the comparison\n value2: any,\n context: Context\n ): boolean {\n // If the items are strictly equal, no need to do a value comparison.\n if (Object.is(value1, value2) || value1 === value2) {\n return true;\n }\n\n // Checks are listed in order of commonality of use-case:\n // 1. Common complex object types (plain object, array)\n // 2. Common data values (date, regexp)\n // 3. Less-common complex object types (map, set)\n // 4. Less-common data values (promise, primitive wrappers)\n // Inherently this is both subjective and assumptive, however\n // when reviewing comparable libraries in the wild this order\n // appears to be generally consistent.\n // Constructors should match, otherwise there is potential for false positives\n // between class and subclass or custom object and POJO.\n if (value1?.constructor !== value2?.constructor) {\n return false;\n }\n\n // `isPlainObject` only checks against the object's own realm. Cross-realm\n // comparisons are rare, and will be handled in the ultimate fallback, so\n // we can avoid capturing the string tag.\n if (value1.constructor === Object) {\n return areObjectsEqual(value1, value2, context);\n }\n\n // `isArray()` works on subclasses and is cross-realm, so we can avoid capturing\n // the string tag or doing an `instanceof` check.\n if (isArray(value1)) {\n return areArraysEqual(value1, value2, context);\n }\n\n // `isTypedArray()` works on all possible TypedArray classes, so we can avoid\n // capturing the string tag or comparing against all possible constructors.\n if (isTypedArray?.(value1)) {\n return areTypedArraysEqual(value1 as TypedArray, value2, context);\n }\n\n // Try to fast-path equality checks for other complex object types in the\n // same realm to avoid capturing the string tag. Strict equality is used\n // instead of `instanceof` because it is more performant for the common\n // use-case. If someone is subclassing a native class, it will be handled\n // with the string tag comparison.\n if (value1.constructor === Date) {\n return areDatesEqual(value1, value2, context);\n }\n\n if (value1.constructor === RegExp) {\n return areRegExpsEqual(value1, value2, context);\n }\n\n if (value1.constructor === Map) {\n return areMapsEqual(value1, value2, context);\n }\n\n if (value1.constructor === Set) {\n return areSetsEqual(value1, value2, context);\n }\n\n // Since this is a custom object, capture the string tag to determine its type.\n const tag = getTag(value1);\n switch (tag) {\n case DATE_TAG: {\n return areDatesEqual(value1, value2, context);\n }\n case REG_EXP_TAG: {\n return areRegExpsEqual(value1, value2, context);\n }\n case MAP_TAG: {\n return areMapsEqual(value1, value2, context);\n }\n case SET_TAG: {\n return areSetsEqual(value1, value2, context);\n }\n case OBJECT_TAG: {\n // The exception for value comparison is custom `Promise`-like class instances. These should\n // be treated the same as standard `Promise` objects, which means strict equality, and if\n // it reaches this point then that strict equality comparison has already failed.\n return (\n typeof value1.then !== 'function' &&\n typeof value2.then !== 'function' &&\n areObjectsEqual(value1, value2, context)\n );\n }\n // If an arguments tag, it should be treated as a standard object.\n case ARGUMENTS_TAG: {\n return areObjectsEqual(value1, value2, context);\n }\n // As the penultimate fallback, check if the values passed are primitive wrappers. This\n // is very rare in modern JS, which is why it is deprioritized compared to all other object\n // types.\n case BOOLEAN_TAG:\n case NUMBER_TAG:\n case STRING_TAG: {\n return arePrimitiveWrappersEqual(value1, value2, context);\n }\n // If not matching any tags that require a specific type of comparison, then we hard-code false because\n // the only thing remaining is strict equality, which has already been compared. This is for a few reasons:\n // - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only\n // comparison that can be made.\n // - For types that can be introspected, but rarely have requirements to be compared\n // (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common\n // use-cases (may be included in a future release, if requested enough).\n // - For types that can be introspected but do not have an objective definition of what\n // equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.\n // In all cases, these decisions should be reevaluated based on changes to the language and\n // common development practices.\n default: {\n return false;\n }\n }\n };\n}\n","/**\n * Slimmed down version of https://github.com/planttheidea/fast-equals\n * Without all the configuration options, and with a few tweaks to make it more readable (though a bit less performant)\n */\n\nimport {\n createEqualityComparatorConfig,\n createInternalEqualityComparator,\n createIsEqual,\n} from './_internal/comparator';\nimport { createEqualityComparator } from './_internal/createEqualityComparator';\n\n/**\n * Compare two values to determine if they are deeply equivalent by value.\n * @param value1 The first value to compare.\n * @param value2 The second value to compare.\n * @returns `true` if the two values are equivalent, `false` otherwise.\n * @example\n * ```ts\n * isEqual(1, 1); // true\n * isEqual(1, '1'); // false\n * isEqual({ a: 1 }, { a: 1 }); // true\n * isEqual({ a: 1 }, { a: 2 }); // false\n * isEqual(new Date('2020-01-01'), new Date('2020-01-01')); // true\n * isEqual(new Set([1, 2, 3]), new Set([3, 2, 1])); // true\n * ```\n */\nexport const isEqual: IsEqual = createCustomEqual();\n\n/**\n * Create a custom equality comparison method.\n *\n * This can be done to create very targeted comparisons in extreme hot-path scenarios\n * where the standard methods are not performant enough, but can also be used to provide\n * support for legacy environments that do not support expected features like\n * `RegExp.prototype.flags` out of the box.\n * @returns A function that can be used to compare values.\n */\nfunction createCustomEqual() {\n const config = createEqualityComparatorConfig();\n const comparator = createEqualityComparator(config);\n const equals = createInternalEqualityComparator(comparator);\n\n return createIsEqual({ comparator, equals });\n}\n\ntype IsEqual = <T1, T2>(value1: T1, value2: T2) => boolean;\n"],"mappings":"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"}