@effect-ts/system
Version:
Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.
371 lines (331 loc) • 8.18 kB
JavaScript
// ets_tracing: off
const HAS_WEAKSET_SUPPORT = typeof WeakSet === "function";
const {
keys
} = Object;
/**
* @function addToCache
*
* add object to cache if an object
*
* @param value the value to potentially add to cache
* @param cache the cache to add to
*/
export function addToCache(value, cache) {
if (value && typeof value === "object") {
cache.add(value);
}
}
/**
* @function hasPair
*
* @description
* does the `pairToMatch` exist in the list of `pairs` provided based on the
* `isEqual` check
*
* @param pairs the pairs to compare against
* @param pairToMatch the pair to match
* @param isEqual the equality comparator used
* @param meta the meta provided
* @returns does the pair exist in the pairs provided
*/
export function hasPair(pairs, pairToMatch, isEqual, meta) {
const {
length
} = pairs;
let pair;
for (let index = 0; index < length; index++) {
pair = pairs[index];
if (isEqual(pair[0], pairToMatch[0], meta) && isEqual(pair[1], pairToMatch[1], meta)) {
return true;
}
}
return false;
}
/**
* @function hasValue
*
* @description
* does the `valueToMatch` exist in the list of `values` provided based on the
* `isEqual` check
*
* @param values the values to compare against
* @param valueToMatch the value to match
* @param isEqual the equality comparator used
* @param meta the meta provided
* @returns does the value exist in the values provided
*/
export function hasValue(values, valueToMatch, isEqual, meta) {
const {
length
} = values;
for (let index = 0; index < length; index++) {
if (isEqual(values[index], valueToMatch, meta)) {
return true;
}
}
return false;
}
/**
* @function sameValueZeroEqual
*
* @description
* are the values passed strictly equal or both NaN
*
* @param a the value to compare against
* @param b the value to test
* @returns are the values equal by the SameValueZero principle
*/
export function sameValueZeroEqual(a, b) {
return a === b || a !== a && b !== b;
}
/**
* @function isPlainObject
*
* @description
* is the value a plain object
*
* @param value the value to test
* @returns is the value a plain object
*/
export function isPlainObject(value) {
return value.constructor === Object || value.constructor == null;
}
/**
* @function isPromiseLike
*
* @description
* is the value promise-like (meaning it is thenable)
*
* @param value the value to test
* @returns is the value promise-like
*/
export function isPromiseLike(value) {
return !!value && typeof value.then === "function";
}
/**
* @function isReactElement
*
* @description
* is the value passed a react element
*
* @param value the value to test
* @returns is the value a react element
*/
export function isReactElement(value) {
return !!(value && value.$$typeof);
}
/**
* @function getNewCacheFallback
*
* @description
* in cases where WeakSet is not supported, creates a new custom
* object that mimics the necessary API aspects for cache purposes
*
* @returns the new cache object
*/
export function getNewCacheFallback() {
return Object.create({
_values: [],
add(value) {
// @ts-expect-error
this._values.push(value);
},
has(value) {
// @ts-expect-error
return this._values.indexOf(value) !== -1;
}
});
}
/**
* @function getNewCache
*
* @description
* get a new cache object to prevent circular references
*
* @returns the new cache object
*/
export const getNewCache = /*#__PURE__*/(canUseWeakMap => {
if (canUseWeakMap) {
return function _getNewCache() {
return new WeakSet();
};
}
return getNewCacheFallback;
})(HAS_WEAKSET_SUPPORT);
/**
* @function createCircularEqualCreator
*
* @description
* create a custom isEqual handler specific to circular objects
*
* @param [isEqual] the isEqual comparator to use instead of isDeepEqual
* @returns the method to create the `isEqual` function
*/
export function createCircularEqualCreator(isEqual) {
return function createCircularEqual(comparator) {
const _comparator = isEqual ? isEqual(comparator) : comparator;
return function circularEqual(a, b, cache = getNewCache()) {
const hasA = cache.has(a);
const hasB = cache.has(b);
if (hasA || hasB) {
return hasA && hasB;
}
addToCache(a, cache);
addToCache(b, cache);
return _comparator(a, b, cache);
};
};
}
/**
* @function toPairs
*
* @description
* convert the map passed into pairs (meaning an array of [key, value] tuples)
*
* @param map the map to convert to [key, value] pairs (entries)
* @returns the [key, value] pairs
*/
export function toPairs(map) {
const pairs = new Array(map.size);
let index = 0;
map.forEach((value, key) => {
pairs[index++] = [key, value];
});
return pairs;
}
/**
* @function toValues
*
* @description
* convert the set passed into values
*
* @param set the set to convert to values
* @returns the values
*/
export function toValues(set) {
const values = new Array(set.size);
let index = 0;
set.forEach(value => {
values[index++] = value;
});
return values;
}
/**
* @function areArraysEqual
*
* @description
* are the arrays equal in value
*
* @param a the array to test
* @param b the array to test against
* @param isEqual the comparator to determine equality
* @param meta the meta object to pass through
* @returns are the arrays equal
*/
export function areArraysEqual(a, b, isEqual, meta) {
const {
length
} = a;
if (b.length !== length) {
return false;
}
for (let index = 0; index < length; index++) {
if (!isEqual(a[index], b[index], meta)) {
return false;
}
}
return true;
}
/**
* @function areMapsEqual
*
* @description
* are the maps equal in value
*
* @param a the map to test
* @param b the map to test against
* @param isEqual the comparator to determine equality
* @param meta the meta map to pass through
* @returns are the maps equal
*/
export function areMapsEqual(a, b, isEqual, meta) {
if (a.size !== b.size) {
return false;
}
const pairsA = toPairs(a);
const pairsB = toPairs(b);
return isEqual(pairsA, pairsB, meta);
}
const OWNER = "_owner";
const hasOwnProperty = /*#__PURE__*/Function.prototype.bind.call(Function.prototype.call, Object.prototype.hasOwnProperty);
/**
* @function areObjectsEqual
*
* @description
* are the objects equal in value
*
* @param a the object to test
* @param b the object to test against
* @param isEqual the comparator to determine equality
* @param meta the meta object to pass through
* @returns are the objects equal
*/
export function areObjectsEqual(a, b, isEqual, meta) {
const keysA = keys(a);
const {
length
} = keysA;
if (keys(b).length !== length) {
return false;
}
let key;
for (let index = 0; index < length; index++) {
key = keysA[index];
if (!hasOwnProperty(b, key)) {
return false;
}
if (key === OWNER && isReactElement(a)) {
if (!isReactElement(b)) {
return false;
}
} else if (!isEqual(a[key], b[key], meta)) {
return false;
}
}
return true;
}
/**
* @function areRegExpsEqual
*
* @description
* are the regExps equal in value
*
* @param a the regExp to test
* @param b the regExp to test agains
* @returns are the regExps equal
*/
export function areRegExpsEqual(a, b) {
return 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;
}
/**
* @function areSetsEqual
*
* @description
* are the sets equal in value
*
* @param a the set to test
* @param b the set to test against
* @param isEqual the comparator to determine equality
* @param meta the meta set to pass through
* @returns are the sets equal
*/
export function areSetsEqual(a, b, isEqual, meta) {
if (a.size !== b.size) {
return false;
}
const valuesA = toValues(a);
const valuesB = toValues(b);
return isEqual(valuesA, valuesB, meta);
}
//# sourceMappingURL=utils.mjs.map