UNPKG

@goatlab/fluent

Version:

Readable query Interface & API generator for TS and Node

1,872 lines (1,711 loc) 62 kB
/** * lodash (Custom Build) <https://lodash.com/> * Build: `lodash modularize exports="npm" -o ./` * Copyright jQuery Foundation and other contributors <https://jquery.org/> * Released under MIT license <https://lodash.com/license> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ /** Used as the size to enable large array optimizations. */ const LARGE_ARRAY_SIZE = 200 /** Used as the `TypeError` message for "Functions" methods. */ const FUNC_ERROR_TEXT = 'Expected a function' /** Used to stand-in for `undefined` hash values. */ const HASH_UNDEFINED = '__lodash_hash_undefined__' /** Used to compose bitmasks for comparison styles. */ const UNORDERED_COMPARE_FLAG = 1 const PARTIAL_COMPARE_FLAG = 2 /** Used as references for various `Number` constants. */ const INFINITY = 1 / 0 const MAX_SAFE_INTEGER = 9007199254740991 /** `Object#toString` result references. */ const argsTag = '[object Arguments]' const arrayTag = '[object Array]' const boolTag = '[object Boolean]' const dateTag = '[object Date]' const errorTag = '[object Error]' const funcTag = '[object Function]' const genTag = '[object GeneratorFunction]' const mapTag = '[object Map]' const numberTag = '[object Number]' const objectTag = '[object Object]' const promiseTag = '[object Promise]' const regexpTag = '[object RegExp]' const setTag = '[object Set]' const stringTag = '[object String]' const symbolTag = '[object Symbol]' const weakMapTag = '[object WeakMap]' const arrayBufferTag = '[object ArrayBuffer]' const dataViewTag = '[object DataView]' const float32Tag = '[object Float32Array]' const float64Tag = '[object Float64Array]' const int8Tag = '[object Int8Array]' const int16Tag = '[object Int16Array]' const int32Tag = '[object Int32Array]' const uint8Tag = '[object Uint8Array]' const uint8ClampedTag = '[object Uint8ClampedArray]' const uint16Tag = '[object Uint16Array]' const uint32Tag = '[object Uint32Array]' /** Used to match property names within property paths. */ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/ const reIsPlainProp = /^\w*$/ const reLeadingDot = /^\./ const rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g /** * Used to match `RegExp` * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ const reRegExpChar = /[\\^$.*+?()[\]{}|]/g /** Used to match backslashes in property paths. */ const reEscapeChar = /\\(\\)?/g /** Used to detect host constructors (Safari). */ const reIsHostCtor = /^\[object .+?Constructor\]$/ /** Used to detect unsigned integer values. */ const reIsUint = /^(?:0|[1-9]\d*)$/ /** Used to identify `toStringTag` values of typed arrays. */ const typedArrayTags = {} typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false /** Detect free variable `global` from Node.js. */ const freeGlobal = typeof global === 'object' && global && global.Object === Object && global /** Detect free variable `self`. */ const freeSelf = typeof self === 'object' && self && self.Object === Object && self /** Used as a reference to the global object. */ const root = freeGlobal || freeSelf || Function('return this')() /** Detect free variable `exports`. */ const freeExports = typeof exports === 'object' && exports && !exports.nodeType && exports /** Detect free variable `module`. */ const freeModule = freeExports && typeof module === 'object' && module && !module.nodeType && module /** Detect the popular CommonJS extension `module.exports`. */ const moduleExports = freeModule && freeModule.exports === freeExports /** Detect free variable `process` from Node.js. */ const freeProcess = moduleExports && freeGlobal.process /** Used to access faster Node.js helpers. */ const nodeUtil = (() => { try { return freeProcess?.binding('util') } catch (_e) {} })() /* Node.js helper references. */ const nodeIsTypedArray = nodeUtil?.isTypedArray /** * A specialized version of `_.some` for arrays without support for iteratee * shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function arraySome(array, predicate) { let index = -1 const length = array ? array.length : 0 while (++index < length) { if (predicate(array[index], index, array)) { return true } } return false } /** * The base implementation of `_.property` without support for deep paths. * * @private * @param {string} key The key of the property to get. * @returns {Function} Returns the new accessor function. */ function baseProperty(key) { return object => (object == null ? undefined : object[key]) } /** * The base implementation of `_.times` without support for iteratee shorthands * or max array length checks. * * @private * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the array of results. */ function baseTimes(n, iteratee) { let index = -1 const result = Array(n) while (++index < n) { result[index] = iteratee(index) } return result } /** * The base implementation of `_.unary` without support for storing metadata. * * @private * @param {Function} func The function to cap arguments for. * @returns {Function} Returns the new capped function. */ function baseUnary(func) { return value => func(value) } /** * Gets the value at `key` of `object`. * * @private * @param {Object} [object] The object to query. * @param {string} key The key of the property to get. * @returns {*} Returns the property value. */ function getValue(object, key) { return object == null ? undefined : object[key] } /** * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ function isHostObject(value) { // Many host objects are `Object` objects that can coerce to strings // despite having improperly defined `toString` methods. let result = false if (value != null && typeof value.toString !== 'function') { try { result = !!`${value}` } catch (_e) {} } return result } /** * Converts `map` to its key-value pairs. * * @private * @param {Object} map The map to convert. * @returns {Array} Returns the key-value pairs. */ function mapToArray(map) { let index = -1 const result = Array(map.size) map.forEach((value, key) => { result[++index] = [key, value] }) return result } /** * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. * @param {Function} transform The argument transform. * @returns {Function} Returns the new function. */ function overArg(func, transform) { return arg => func(transform(arg)) } /** * Converts `set` to an array of its values. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the values. */ function setToArray(set) { let index = -1 const result = Array(set.size) set.forEach(value => { result[++index] = value }) return result } /** Used for built-in method references. */ const arrayProto = Array.prototype const funcProto = Function.prototype const objectProto = Object.prototype /** Used to detect overreaching core-js shims. */ const coreJsData = root['__core-js_shared__'] /** Used to detect methods masquerading as native. */ const maskSrcKey = (() => { const uid = /[^.]+$/.exec(coreJsData?.keys?.IE_PROTO || '') return uid ? `Symbol(src)_1.${uid}` : '' })() /** Used to resolve the decompiled source of functions. */ const funcToString = funcProto.toString /** Used to check objects for own properties. */ const hasOwnProperty = objectProto.hasOwnProperty /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ const objectToString = objectProto.toString /** Used to detect if a method is native. */ const reIsNative = RegExp( '^' + funcToString .call(hasOwnProperty) .replace(reRegExpChar, '\\$&') .replace( /hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?' ) + '$' ) /** Built-in value references. */ const Symbol = root.Symbol const Uint8Array = root.Uint8Array const propertyIsEnumerable = objectProto.propertyIsEnumerable const splice = arrayProto.splice /* Built-in method references for those with the same name as other `lodash` methods. */ const nativeKeys = overArg(Object.keys, Object) /* Built-in method references that are verified to be native. */ const DataView = getNative(root, 'DataView') const Map = getNative(root, 'Map') const Promise = getNative(root, 'Promise') const Set = getNative(root, 'Set') const WeakMap = getNative(root, 'WeakMap') const nativeCreate = getNative(Object, 'create') /** Used to detect maps, sets, and weakmaps. */ const dataViewCtorString = toSource(DataView) const mapCtorString = toSource(Map) const promiseCtorString = toSource(Promise) const setCtorString = toSource(Set) const weakMapCtorString = toSource(WeakMap) /** Used to convert symbols to primitives and strings. */ const symbolProto = Symbol ? Symbol.prototype : undefined const symbolValueOf = symbolProto ? symbolProto.valueOf : undefined const symbolToString = symbolProto ? symbolProto.toString : undefined /** * Creates a hash object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Hash(entries) { let index = -1 const length = entries ? entries.length : 0 this.clear() while (++index < length) { const entry = entries[index] this.set(entry[0], entry[1]) } } /** * Removes all key-value entries from the hash. * * @private * @name clear * @memberOf Hash */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {} } /** * Removes `key` and its value from the hash. * * @private * @name delete * @memberOf Hash * @param {Object} hash The hash to modify. * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { return this.has(key) && delete this.__data__[key] } /** * Gets the hash value for `key`. * * @private * @name get * @memberOf Hash * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function hashGet(key) { const data = this.__data__ if (nativeCreate) { const result = data[key] return result === HASH_UNDEFINED ? undefined : result } return hasOwnProperty.call(data, key) ? data[key] : undefined } /** * Checks if a hash value for `key` exists. * * @private * @name has * @memberOf Hash * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function hashHas(key) { const data = this.__data__ return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key) } /** * Sets the hash `key` to `value`. * * @private * @name set * @memberOf Hash * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the hash instance. */ function hashSet(key, value) { const data = this.__data__ data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value return this } // Add methods to `Hash`. Hash.prototype.clear = hashClear Hash.prototype.delete = hashDelete Hash.prototype.get = hashGet Hash.prototype.has = hashHas Hash.prototype.set = hashSet /** * Creates an list cache object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function ListCache(entries) { let index = -1 const length = entries ? entries.length : 0 this.clear() while (++index < length) { const entry = entries[index] this.set(entry[0], entry[1]) } } /** * Removes all key-value entries from the list cache. * * @private * @name clear * @memberOf ListCache */ function listCacheClear() { this.__data__ = [] } /** * Removes `key` and its value from the list cache. * * @private * @name delete * @memberOf ListCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function listCacheDelete(key) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { return false } const lastIndex = data.length - 1 if (index === lastIndex) { data.pop() } else { splice.call(data, index, 1) } return true } /** * Gets the list cache value for `key`. * * @private * @name get * @memberOf ListCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function listCacheGet(key) { const data = this.__data__ const index = assocIndexOf(data, key) return index < 0 ? undefined : data[index][1] } /** * Checks if a list cache value for `key` exists. * * @private * @name has * @memberOf ListCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function listCacheHas(key) { return assocIndexOf(this.__data__, key) > -1 } /** * Sets the list cache `key` to `value`. * * @private * @name set * @memberOf ListCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the list cache instance. */ function listCacheSet(key, value) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { data.push([key, value]) } else { data[index][1] = value } return this } // Add methods to `ListCache`. ListCache.prototype.clear = listCacheClear ListCache.prototype.delete = listCacheDelete ListCache.prototype.get = listCacheGet ListCache.prototype.has = listCacheHas ListCache.prototype.set = listCacheSet /** * Creates a map cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function MapCache(entries) { let index = -1 const length = entries ? entries.length : 0 this.clear() while (++index < length) { const entry = entries[index] this.set(entry[0], entry[1]) } } /** * Removes all key-value entries from the map. * * @private * @name clear * @memberOf MapCache */ function mapCacheClear() { this.__data__ = { hash: new Hash(), map: new (Map || ListCache)(), string: new Hash() } } /** * Removes `key` and its value from the map. * * @private * @name delete * @memberOf MapCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { return getMapData(this, key).delete(key) } /** * Gets the map value for `key`. * * @private * @name get * @memberOf MapCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function mapCacheGet(key) { return getMapData(this, key).get(key) } /** * Checks if a map value for `key` exists. * * @private * @name has * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapCacheHas(key) { return getMapData(this, key).has(key) } /** * Sets the map `key` to `value`. * * @private * @name set * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { getMapData(this, key).set(key, value) return this } // Add methods to `MapCache`. MapCache.prototype.clear = mapCacheClear MapCache.prototype.delete = mapCacheDelete MapCache.prototype.get = mapCacheGet MapCache.prototype.has = mapCacheHas MapCache.prototype.set = mapCacheSet /** * * Creates an array cache object to store unique values. * * @private * @constructor * @param {Array} [values] The values to cache. */ function SetCache(values) { let index = -1 const length = values ? values.length : 0 this.__data__ = new MapCache() while (++index < length) { this.add(values[index]) } } /** * Adds `value` to the array cache. * * @private * @name add * @memberOf SetCache * @alias push * @param {*} value The value to cache. * @returns {Object} Returns the cache instance. */ function setCacheAdd(value) { this.__data__.set(value, HASH_UNDEFINED) return this } /** * Checks if `value` is in the array cache. * * @private * @name has * @memberOf SetCache * @param {*} value The value to search for. * @returns {number} Returns `true` if `value` is found, else `false`. */ function setCacheHas(value) { return this.__data__.has(value) } // Add methods to `SetCache`. SetCache.prototype.add = SetCache.prototype.push = setCacheAdd SetCache.prototype.has = setCacheHas /** * Creates a stack cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { this.__data__ = new ListCache(entries) } /** * Removes all key-value entries from the stack. * * @private * @name clear * @memberOf Stack */ function stackClear() { this.__data__ = new ListCache() } /** * Removes `key` and its value from the stack. * * @private * @name delete * @memberOf Stack * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { return this.__data__.delete(key) } /** * Gets the stack value for `key`. * * @private * @name get * @memberOf Stack * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function stackGet(key) { return this.__data__.get(key) } /** * Checks if a stack value for `key` exists. * * @private * @name has * @memberOf Stack * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function stackHas(key) { return this.__data__.has(key) } /** * Sets the stack `key` to `value`. * * @private * @name set * @memberOf Stack * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { let cache = this.__data__ if (cache instanceof ListCache) { const pairs = cache.__data__ if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) { pairs.push([key, value]) return this } cache = this.__data__ = new MapCache(pairs) } cache.set(key, value) return this } // Add methods to `Stack`. Stack.prototype.clear = stackClear Stack.prototype.delete = stackDelete Stack.prototype.get = stackGet Stack.prototype.has = stackHas Stack.prototype.set = stackSet /** * Creates an array of the enumerable property names of the array-like `value`. * * @private * @param {*} value The value to query. * @param {boolean} inherited Specify returning inherited property names. * @returns {Array} Returns the array of property names. */ function arrayLikeKeys(value, inherited) { // Safari 8.1 makes `arguments.callee` enumerable in strict mode. // Safari 9 makes `arguments.length` enumerable in strict mode. const result = isArray(value) || isArguments(value) ? baseTimes(value.length, String) : [] const length = result.length const skipIndexes = !!length for (const key in value) { if ( (inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key === 'length' || isIndex(key, length))) ) { result.push(key) } } return result } /** * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private * @param {Array} array The array to inspect. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ function assocIndexOf(array, key) { let length = array.length while (length--) { if (eq(array[length][0], key)) { return length } } return -1 } /** * The base implementation of `baseForOwn` which iterates over `object` * properties returned by `keysFunc` and invokes `iteratee` for each property. * Iteratee functions may exit iteration early by explicitly returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ const baseFor = createBaseFor() /** * The base implementation of `_.forOwn` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return object && baseFor(object, iteratee, keys) } /** * The base implementation of `_.get` without support for default values. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @returns {*} Returns the resolved value. */ function baseGet(object, path) { path = isKey(path, object) ? [path] : castPath(path) let index = 0 const length = path.length while (object != null && index < length) { object = object[toKey(path[index++])] } return index && index === length ? object : undefined } /** * The base implementation of `getTag`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function baseGetTag(value) { return objectToString.call(value) } /** * The base implementation of `_.hasIn` without support for deep paths. * * @private * @param {Object} [object] The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHasIn(object, key) { return object != null && key in Object(object) } /** * The base implementation of `_.isEqual` which supports partial comparisons * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. * @param {boolean} [bitmask] The bitmask of comparison flags. * The bitmask may be composed of the following flags: * 1 - Unordered comparison * 2 - Partial comparison * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, bitmask, stack) { if (value === other) { return true } if ( value == null || other == null || (!isObject(value) && !isObjectLike(other)) ) { return value !== value && other !== other } return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack) } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { const objIsArr = isArray(object) const othIsArr = isArray(other) let objTag = arrayTag let othTag = arrayTag if (!objIsArr) { objTag = getTag(object) objTag = objTag === argsTag ? objectTag : objTag } if (!othIsArr) { othTag = getTag(other) othTag = othTag === argsTag ? objectTag : othTag } const objIsObj = objTag === objectTag && !isHostObject(object) const othIsObj = othTag === objectTag && !isHostObject(other) const isSameTag = objTag === othTag if (isSameTag && !objIsObj) { stack || (stack = new Stack()) return objIsArr || isTypedArray(object) ? equalArrays(object, other, equalFunc, customizer, bitmask, stack) : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack) } if (!(bitmask & PARTIAL_COMPARE_FLAG)) { const objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__') const othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__') if (objIsWrapped || othIsWrapped) { const objUnwrapped = objIsWrapped ? object.value() : object const othUnwrapped = othIsWrapped ? other.value() : other stack || (stack = new Stack()) return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack) } } if (!isSameTag) { return false } stack || (stack = new Stack()) return equalObjects(object, other, equalFunc, customizer, bitmask, stack) } /** * The base implementation of `_.isMatch` without support for iteratee shorthands. * * @private * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Array} matchData The property names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, source, matchData, customizer) { let index = matchData.length const length = index const noCustomizer = !customizer if (object == null) { return !length } object = Object(object) while (index--) { const data = matchData[index] if ( noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object) ) { return false } } while (++index < length) { data = matchData[index] const key = data[0] const objValue = object[key] const srcValue = data[1] if (noCustomizer && data[2]) { if (objValue === undefined && !(key in object)) { return false } } else { const stack = new Stack() if (customizer) { const _result = customizer( objValue, srcValue, key, object, source, stack ) } if ( !(result === undefined ? baseIsEqual( srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack ) : result) ) { return false } } } return true } /** * The base implementation of `_.isNative` without bad shim checks. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, * else `false`. */ function baseIsNative(value) { if (!isObject(value) || isMasked(value)) { return false } const pattern = isFunction(value) || isHostObject(value) ? reIsNative : reIsHostCtor return pattern.test(toSource(value)) } /** * The base implementation of `_.isTypedArray` without Node.js optimizations. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. */ function baseIsTypedArray(value) { return ( isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objectToString.call(value)] ) } /** * The base implementation of `_.iteratee`. * * @private * @param {*} [value=_.identity] The value to convert to an iteratee. * @returns {Function} Returns the iteratee. */ function baseIteratee(value) { // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. if (typeof value === 'function') { return value } if (value == null) { return identity } if (typeof value === 'object') { return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value) } return property(value) } /** * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { if (!isPrototype(object)) { return nativeKeys(object) } const result = [] for (const key in Object(object)) { if (hasOwnProperty.call(object, key) && key !== 'constructor') { result.push(key) } } return result } /** * The base implementation of `_.matches` which doesn't clone `source`. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new spec function. */ function baseMatches(source) { const matchData = getMatchData(source) if (matchData.length === 1 && matchData[0][2]) { return matchesStrictComparable(matchData[0][0], matchData[0][1]) } return object => object === source || baseIsMatch(object, source, matchData) } /** * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. * * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function baseMatchesProperty(path, srcValue) { if (isKey(path) && isStrictComparable(srcValue)) { return matchesStrictComparable(toKey(path), srcValue) } return object => { const objValue = get(object, path) return objValue === undefined && objValue === srcValue ? hasIn(object, path) : baseIsEqual( srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG ) } } /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new accessor function. */ function basePropertyDeep(path) { return object => baseGet(object, path) } /** * The base implementation of `_.toString` which doesn't convert nullish * values to empty strings. * * @private * @param {*} value The value to process. * @returns {string} Returns the string. */ function baseToString(value) { // Exit early for strings to avoid a performance hit in some environments. if (typeof value === 'string') { return value } if (isSymbol(value)) { return symbolToString ? symbolToString.call(value) : '' } const result = `${value}` return result === '0' && 1 / value === -INFINITY ? '-0' : result } /** * Casts `value` to a path array if it's not one. * * @private * @param {*} value The value to inspect. * @returns {Array} Returns the cast property path array. */ function castPath(value) { return isArray(value) ? value : stringToPath(value) } /** * Creates a base function for methods like `_.forIn` and `_.forOwn`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseFor(fromRight) { return (object, iteratee, keysFunc) => { let index = -1 const iterable = Object(object) const props = keysFunc(object) let length = props.length while (length--) { const key = props[fromRight ? length : ++index] if (iteratee(iterable[key], key, iterable) === false) { break } } return object } } /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { const isPartial = bitmask & PARTIAL_COMPARE_FLAG const arrLength = array.length const othLength = other.length if (arrLength !== othLength && !(isPartial && othLength > arrLength)) { return false } // Assume cyclic values are equal. const stacked = stack.get(array) if (stacked && stack.get(other)) { return stacked === other } let index = -1 let result = true const seen = bitmask & UNORDERED_COMPARE_FLAG ? new SetCache() : undefined stack.set(array, other) stack.set(other, array) // Ignore non-index properties. while (++index < arrLength) { const arrValue = array[index] const othValue = other[index] if (customizer) { const _compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack) } if (compared !== undefined) { if (compared) { continue } result = false break } // Recursively compare arrays (susceptible to call stack limits). if (seen) { if ( !arraySome(other, (othValue, othIndex) => { if ( !seen.has(othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack)) ) { return seen.add(othIndex) } }) ) { result = false break } } else if ( !( arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack) ) ) { result = false break } } stack.delete(array) stack.delete(other) return result } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) { switch (tag) { case dataViewTag: if ( object.byteLength !== other.byteLength || object.byteOffset !== other.byteOffset ) { return false } object = object.buffer other = other.buffer case arrayBufferTag: if ( object.byteLength !== other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other)) ) { return false } return true case boolTag: case dateTag: case numberTag: // Coerce booleans to `1` or `0` and dates to milliseconds. // Invalid dates are coerced to `NaN`. return eq(+object, +other) case errorTag: return object.name === other.name && object.message === other.message case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring // for more details. return object === `${other}` case mapTag: { const _convert = mapToArray } case setTag: { const isPartial = bitmask & PARTIAL_COMPARE_FLAG convert || (convert = setToArray) if (object.size !== other.size && !isPartial) { return false } // Assume cyclic values are equal. const stacked = stack.get(object) if (stacked) { return stacked === other } bitmask |= UNORDERED_COMPARE_FLAG // Recursively compare objects (susceptible to call stack limits). stack.set(object, other) const result = equalArrays( convert(object), convert(other), equalFunc, customizer, bitmask, stack ) stack.delete(object) return result } case symbolTag: if (symbolValueOf) { return symbolValueOf.call(object) === symbolValueOf.call(other) } } return false } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { const isPartial = bitmask & PARTIAL_COMPARE_FLAG const objProps = keys(object) const objLength = objProps.length const othProps = keys(other) const othLength = othProps.length if (objLength !== othLength && !isPartial) { return false } let index = objLength while (index--) { const key = objProps[index] if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false } } // Assume cyclic values are equal. const stacked = stack.get(object) if (stacked && stack.get(other)) { return stacked === other } let result = true stack.set(object, other) stack.set(other, object) let skipCtor = isPartial while (++index < objLength) { key = objProps[index] const objValue = object[key] const othValue = other[key] if (customizer) { const _compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack) } // Recursively compare objects (susceptible to call stack limits). if ( !(compared === undefined ? objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack) : compared) ) { result = false break } skipCtor || (skipCtor = key === 'constructor') } if (result && !skipCtor) { const objCtor = object.constructor const othCtor = other.constructor // Non `Object` object instances with different constructors are not equal. if ( objCtor !== othCtor && 'constructor' in object && 'constructor' in other && !( typeof objCtor === 'function' && objCtor instanceof objCtor && typeof othCtor === 'function' && othCtor instanceof othCtor ) ) { result = false } } stack.delete(object) stack.delete(other) return result } /** * Gets the data for `map`. * * @private * @param {Object} map The map to query. * @param {string} key The reference key. * @returns {*} Returns the map data. */ function getMapData(map, key) { const data = map.__data__ return isKeyable(key) ? data[typeof key === 'string' ? 'string' : 'hash'] : data.map } /** * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { const result = keys(object) let length = result.length while (length--) { const key = result[length] const value = object[key] result[length] = [key, value, isStrictComparable(value)] } return result } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { const value = getValue(object, key) return baseIsNative(value) ? value : undefined } /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ let getTag = baseGetTag // Fallback for data views, maps, sets, and weak maps in IE 11, // for data views in Edge < 14, and promises in Node.js. if ( (DataView && getTag(new DataView(new ArrayBuffer(1))) !== dataViewTag) || (Map && getTag(new Map()) !== mapTag) || (Promise && getTag(Promise.resolve()) !== promiseTag) || (Set && getTag(new Set()) !== setTag) || (WeakMap && getTag(new WeakMap()) !== weakMapTag) ) { getTag = value => { const result = objectToString.call(value) const Ctor = result === objectTag ? value.constructor : undefined const ctorString = Ctor ? toSource(Ctor) : undefined if (ctorString) { switch (ctorString) { case dataViewCtorString: return dataViewTag case mapCtorString: return mapTag case promiseCtorString: return promiseTag case setCtorString: return setTag case weakMapCtorString: return weakMapTag } } return result } } /** * Checks if `path` exists on `object`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @param {Function} hasFunc The function to check properties. * @returns {boolean} Returns `true` if `path` exists, else `false`. */ function hasPath(object, path, hasFunc) { path = isKey(path, object) ? [path] : castPath(path) let result let index = -1 const _length = path.length while (++index < length) { const key = toKey(path[index]) if (!(result = object != null && hasFunc(object, key))) { break } object = object[key] } if (result) { return result } const length = object ? object.length : 0 return ( !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)) ) } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { length = length == null ? MAX_SAFE_INTEGER : length return ( !!length && (typeof value === 'number' || reIsUint.test(value)) && value > -1 && value % 1 === 0 && value < length ) } /** * Checks if `value` is a property name and not a property path. * * @private * @param {*} value The value to check. * @param {Object} [object] The object to query keys on. * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { if (isArray(value)) { return false } const type = typeof value if ( type === 'number' || type === 'symbol' || type === 'boolean' || value == null || isSymbol(value) ) { return true } return ( reIsPlainProp.test(value) || !reIsDeepProp.test(value) || (object != null && value in Object(object)) ) } /** * Checks if `value` is suitable for use as unique object key. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is suitable, else `false`. */ function isKeyable(value) { const type = typeof value return type === 'string' || type === 'number' || type === 'symbol' || type === 'boolean' ? value !== '__proto__' : value === null } /** * Checks if `func` has its source masked. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` is masked, else `false`. */ function isMasked(func) { return !!maskSrcKey && maskSrcKey in func } /** * Checks if `value` is likely a prototype object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ function isPrototype(value) { const Ctor = value?.constructor const proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto return value === proto } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && !isObject(value) } /** * A specialized version of `matchesProperty` for source values suitable * for strict equality comparisons, i.e. `===`. * * @private * @param {string} key The key of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function matchesStrictComparable(key, srcValue) { return object => { if (object == null) { return false } return ( object[key] === srcValue && (srcValue !== undefined || key in Object(object)) ) } } /** * Converts `string` to a property path array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ const stringToPath = memoize(string => { string = toString(string) const result = [] if (reLeadingDot.test(string)) { result.push('') } string.replace(rePropName, (match, number, quote, string) => { result.push(quote ? string.replace(reEscapeChar, '$1') : number || match) }) return result }) /** * Converts `value` to a string key if it's not a string or symbol. * * @private * @param {*} value The value to inspect. * @returns {string|symbol} Returns the key. */ function toKey(value) { if (typeof value === 'string' || isSymbol(value)) { return value } const result = `${value}` return result === '0' && 1 / value === -INFINITY ? '-0' : result } /** * Converts `func` to its source code. * * @private * @param {Function} func The function to process. * @returns {string} Returns the source code. */ function toSource(func) { if (func != null) { try { return funcToString.call(func) } catch (_e) {} try { return `${func}` } catch (_e) {} } return '' } /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided, it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the map cache key. The `func` * is invoked with the `this` binding of the memoized function. * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) * method interface of `delete`, `get`, `has`, and `set`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoized function. * @example * * var object = { 'a': 1, 'b': 2 }; * var other = { 'c': 3, 'd': 4 }; * * var values = _.memoize(_.values); * values(object); * // => [1, 2] * * values(other); * // => [3, 4] * * object.a = 2; * values(object); * // => [1, 2] * * // Modify the result cache. * values.cache.set(object, ['a', 'b']); * values(object); * // => ['a', 'b'] * * // Replace `_.memoize.Cache`. * _.memoize.Cache = WeakMap; */ function memoize(func, resolver) { if ( typeof func !== 'function' || (resolver && typeof resolver !== 'function') ) { throw new TypeError(FUNC_ERROR_TEXT) } const memoized = function () { const args = argum