diff --git a/README.md b/README.md index d349b8d0a..d9264f396 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# lodash-amd v4.15.0 +# lodash-amd v4.16.0 The [Lodash](https://lodash.com/) library exported as [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) modules. Generated using [lodash-cli](https://www.npmjs.com/package/lodash-cli): -```bash +```shell $ lodash exports=amd -o ./ $ lodash exports=amd -d -o ./main.js ``` @@ -11,8 +11,8 @@ $ lodash exports=amd -d -o ./main.js ## Installation Using npm: -```bash -$ {sudo -H} npm i -g npm +```shell +$ npm i -g npm $ npm i --save lodash-amd ``` @@ -27,4 +27,4 @@ require({ }); ``` -See the [package source](https://github.com/lodash/lodash/tree/4.15.0-amd) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.16.0-amd) for more details. diff --git a/_Stack.js b/_Stack.js index 2d994df7b..941bc9b2b 100644 --- a/_Stack.js +++ b/_Stack.js @@ -8,7 +8,8 @@ define(['./_ListCache', './_stackClear', './_stackDelete', './_stackGet', './_st * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { - this.__data__ = new ListCache(entries); + var data = this.__data__ = new ListCache(entries); + this.size = data.size; } // Add methods to `Stack`. diff --git a/_arraySample.js b/_arraySample.js new file mode 100644 index 000000000..a299252b6 --- /dev/null +++ b/_arraySample.js @@ -0,0 +1,20 @@ +define(['./_baseRandom'], function(baseRandom) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** + * A specialized version of `_.sample` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + return arraySample; +}); diff --git a/_arraySampleSize.js b/_arraySampleSize.js new file mode 100644 index 000000000..bc4c20f9e --- /dev/null +++ b/_arraySampleSize.js @@ -0,0 +1,18 @@ +define(['./_arrayShuffle', './_baseClamp'], function(arrayShuffle, baseClamp) { + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + var result = arrayShuffle(array); + result.length = baseClamp(n, 0, result.length); + return result; + } + + return arraySampleSize; +}); diff --git a/_arrayShuffle.js b/_arrayShuffle.js new file mode 100644 index 000000000..70384a043 --- /dev/null +++ b/_arrayShuffle.js @@ -0,0 +1,15 @@ +define(['./_copyArray', './_shuffleSelf'], function(copyArray, shuffleSelf) { + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + return arrayShuffle; +}); diff --git a/_assignMergeValue.js b/_assignMergeValue.js index 72f37972d..1c013c0db 100644 --- a/_assignMergeValue.js +++ b/_assignMergeValue.js @@ -1,4 +1,4 @@ -define(['./eq'], function(eq) { +define(['./_baseAssignValue', './eq'], function(baseAssignValue, eq) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -15,7 +15,7 @@ define(['./eq'], function(eq) { function assignMergeValue(object, key, value) { if ((value !== undefined && !eq(object[key], value)) || (typeof key == 'number' && value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); } } diff --git a/_assignValue.js b/_assignValue.js index c6a7cba31..445a462be 100644 --- a/_assignValue.js +++ b/_assignValue.js @@ -1,4 +1,4 @@ -define(['./eq'], function(eq) { +define(['./_baseAssignValue', './eq'], function(baseAssignValue, eq) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -23,7 +23,7 @@ define(['./eq'], function(eq) { var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); } } diff --git a/_baseAssignValue.js b/_baseAssignValue.js new file mode 100644 index 000000000..82e5d8b94 --- /dev/null +++ b/_baseAssignValue.js @@ -0,0 +1,29 @@ +define([], function() { + + /** Built-in value references. */ + var defineProperty = Object.defineProperty; + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + return baseAssignValue; +}); diff --git a/_baseClone.js b/_baseClone.js index b0711e0b8..e1ceb4989 100644 --- a/_baseClone.js +++ b/_baseClone.js @@ -1,4 +1,4 @@ -define(['./_Stack', './_arrayEach', './_assignValue', './_baseAssign', './_cloneBuffer', './_copyArray', './_copySymbols', './_getAllKeys', './_getTag', './_initCloneArray', './_initCloneByTag', './_initCloneObject', './isArray', './isBuffer', './_isHostObject', './isObject', './keys'], function(Stack, arrayEach, assignValue, baseAssign, cloneBuffer, copyArray, copySymbols, getAllKeys, getTag, initCloneArray, initCloneByTag, initCloneObject, isArray, isBuffer, isHostObject, isObject, keys) { +define(['./_Stack', './_arrayEach', './_assignValue', './_baseAssign', './_cloneBuffer', './_copyArray', './_copySymbols', './_getAllKeys', './_getTag', './_initCloneArray', './_initCloneByTag', './_initCloneObject', './isArray', './isBuffer', './isObject', './keys'], function(Stack, arrayEach, assignValue, baseAssign, cloneBuffer, copyArray, copySymbols, getAllKeys, getTag, initCloneArray, initCloneByTag, initCloneObject, isArray, isBuffer, isObject, keys) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -87,9 +87,6 @@ define(['./_Stack', './_arrayEach', './_assignValue', './_baseAssign', './_clone return cloneBuffer(value, isDeep); } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { - if (isHostObject(value)) { - return object ? value : {}; - } result = initCloneObject(isFunc ? {} : value); if (!isDeep) { return copySymbols(value, baseAssign(result, value)); diff --git a/_baseIndexOf.js b/_baseIndexOf.js index 05f772f5c..505794744 100644 --- a/_baseIndexOf.js +++ b/_baseIndexOf.js @@ -1,4 +1,4 @@ -define(['./_baseFindIndex', './_baseIsNaN'], function(baseFindIndex, baseIsNaN) { +define(['./_baseFindIndex', './_baseIsNaN', './_strictIndexOf'], function(baseFindIndex, baseIsNaN, strictIndexOf) { /** * The base implementation of `_.indexOf` without `fromIndex` bounds checks. @@ -10,18 +10,9 @@ define(['./_baseFindIndex', './_baseIsNaN'], function(baseFindIndex, baseIsNaN) * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { - if (value !== value) { - return baseFindIndex(array, baseIsNaN, fromIndex); - } - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); } return baseIndexOf; diff --git a/_baseIsEqualDeep.js b/_baseIsEqualDeep.js index 2b66ab08d..e003d0753 100644 --- a/_baseIsEqualDeep.js +++ b/_baseIsEqualDeep.js @@ -1,4 +1,4 @@ -define(['./_Stack', './_equalArrays', './_equalByTag', './_equalObjects', './_getTag', './isArray', './_isHostObject', './isTypedArray'], function(Stack, equalArrays, equalByTag, equalObjects, getTag, isArray, isHostObject, isTypedArray) { +define(['./_Stack', './_equalArrays', './_equalByTag', './_equalObjects', './_getTag', './isArray', './isTypedArray'], function(Stack, equalArrays, equalByTag, equalObjects, getTag, isArray, isTypedArray) { /** Used to compose bitmasks for comparison styles. */ var PARTIAL_COMPARE_FLAG = 2; @@ -43,8 +43,8 @@ define(['./_Stack', './_equalArrays', './_equalByTag', './_equalObjects', './_ge othTag = getTag(other); othTag = othTag == argsTag ? objectTag : othTag; } - var objIsObj = objTag == objectTag && !isHostObject(object), - othIsObj = othTag == objectTag && !isHostObject(other), + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, isSameTag = objTag == othTag; if (isSameTag && !objIsObj) { diff --git a/_baseIsNative.js b/_baseIsNative.js index 535b9022a..525ec8708 100644 --- a/_baseIsNative.js +++ b/_baseIsNative.js @@ -1,4 +1,4 @@ -define(['./isFunction', './_isHostObject', './_isMasked', './isObject', './_toSource'], function(isFunction, isHostObject, isMasked, isObject, toSource) { +define(['./isFunction', './_isMasked', './isObject', './_toSource'], function(isFunction, isMasked, isObject, toSource) { /** * Used to match `RegExp` @@ -37,7 +37,7 @@ define(['./isFunction', './_isHostObject', './_isMasked', './isObject', './_toSo if (!isObject(value) || isMasked(value)) { return false; } - var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; return pattern.test(toSource(value)); } diff --git a/_basePickBy.js b/_basePickBy.js index 396df10cb..9072e2b06 100644 --- a/_basePickBy.js +++ b/_basePickBy.js @@ -1,4 +1,4 @@ -define([], function() { +define(['./_baseAssignValue'], function(baseAssignValue) { /** * The base implementation of `_.pickBy` without support for iteratee shorthands. @@ -19,7 +19,7 @@ define([], function() { value = object[key]; if (predicate(value, key)) { - result[key] = value; + baseAssignValue(result, key, value); } } return result; diff --git a/_baseRest.js b/_baseRest.js index f2a6ca592..e52185225 100644 --- a/_baseRest.js +++ b/_baseRest.js @@ -1,10 +1,4 @@ -define(['./_apply'], function(apply) { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max; +define(['./identity', './_overRest', './_setToString'], function(identity, overRest, setToString) { /** * The base implementation of `_.rest` which doesn't validate or coerce arguments. @@ -15,24 +9,7 @@ define(['./_apply'], function(apply) { * @returns {Function} Returns the new function. */ function baseRest(func, start) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = array; - return apply(func, this, otherArgs); - }; + return setToString(overRest(func, start, identity), func + ''); } return baseRest; diff --git a/_baseSetData.js b/_baseSetData.js index 05cafb328..e2d634fb4 100644 --- a/_baseSetData.js +++ b/_baseSetData.js @@ -1,7 +1,7 @@ define(['./identity', './_metaMap'], function(identity, metaMap) { /** - * The base implementation of `setData` without support for hot loop detection. + * The base implementation of `setData` without support for hot loop shorting. * * @private * @param {Function} func The function to associate metadata with. diff --git a/_baseSetToString.js b/_baseSetToString.js new file mode 100644 index 000000000..7a51c0d21 --- /dev/null +++ b/_baseSetToString.js @@ -0,0 +1,21 @@ +define(['./constant', './identity', './_nativeDefineProperty'], function(constant, identity, nativeDefineProperty) { + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !nativeDefineProperty ? identity : function(func, string) { + return nativeDefineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + return baseSetToString; +}); diff --git a/_cacheHas.js b/_cacheHas.js index 9aac2b688..456bdc496 100644 --- a/_cacheHas.js +++ b/_cacheHas.js @@ -1,7 +1,7 @@ define([], function() { /** - * Checks if a cache value for `key` exists. + * Checks if a `cache` value for `key` exists. * * @private * @param {Object} cache The cache to query. diff --git a/_castRest.js b/_castRest.js new file mode 100644 index 000000000..2971a14d2 --- /dev/null +++ b/_castRest.js @@ -0,0 +1,15 @@ +define(['./_baseRest'], function(baseRest) { + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + return castRest; +}); diff --git a/_copyObject.js b/_copyObject.js index 4e41d3a41..922ce9d5d 100644 --- a/_copyObject.js +++ b/_copyObject.js @@ -1,4 +1,4 @@ -define(['./_assignValue'], function(assignValue) { +define(['./_assignValue', './_baseAssignValue'], function(assignValue, baseAssignValue) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -14,6 +14,7 @@ define(['./_assignValue'], function(assignValue) { * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { + var isNew = !object; object || (object = {}); var index = -1, @@ -26,7 +27,14 @@ define(['./_assignValue'], function(assignValue) { ? customizer(object[key], source[key], key, object, source) : undefined; - assignValue(object, key, newValue === undefined ? source[key] : newValue); + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } } return object; } diff --git a/_countHolders.js b/_countHolders.js index 9905d0ca6..6d840549f 100644 --- a/_countHolders.js +++ b/_countHolders.js @@ -14,7 +14,7 @@ define([], function() { while (length--) { if (array[length] === placeholder) { - result++; + ++result; } } return result; diff --git a/_createFlow.js b/_createFlow.js index 5ea89772b..1a2ac9cb0 100644 --- a/_createFlow.js +++ b/_createFlow.js @@ -1,4 +1,4 @@ -define(['./_LodashWrapper', './_baseFlatten', './_baseRest', './_getData', './_getFuncName', './isArray', './_isLaziable'], function(LodashWrapper, baseFlatten, baseRest, getData, getFuncName, isArray, isLaziable) { +define(['./_LodashWrapper', './_flatRest', './_getData', './_getFuncName', './isArray', './_isLaziable'], function(LodashWrapper, flatRest, getData, getFuncName, isArray, isLaziable) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -23,9 +23,7 @@ define(['./_LodashWrapper', './_baseFlatten', './_baseRest', './_getData', './_g * @returns {Function} Returns the new flow function. */ function createFlow(fromRight) { - return baseRest(function(funcs) { - funcs = baseFlatten(funcs, 1); - + return flatRest(function(funcs) { var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; diff --git a/_createOver.js b/_createOver.js index dc19d997c..a8d221082 100644 --- a/_createOver.js +++ b/_createOver.js @@ -1,4 +1,4 @@ -define(['./_apply', './_arrayMap', './_baseFlatten', './_baseIteratee', './_baseRest', './_baseUnary', './isArray'], function(apply, arrayMap, baseFlatten, baseIteratee, baseRest, baseUnary, isArray) { +define(['./_apply', './_arrayMap', './_baseIteratee', './_baseRest', './_baseUnary', './_flatRest'], function(apply, arrayMap, baseIteratee, baseRest, baseUnary, flatRest) { /** * Creates a function like `_.over`. @@ -8,11 +8,8 @@ define(['./_apply', './_arrayMap', './_baseFlatten', './_baseIteratee', './_base * @returns {Function} Returns the new over function. */ function createOver(arrayFunc) { - return baseRest(function(iteratees) { - iteratees = (iteratees.length == 1 && isArray(iteratees[0])) - ? arrayMap(iteratees[0], baseUnary(baseIteratee)) - : arrayMap(baseFlatten(iteratees, 1), baseUnary(baseIteratee)); - + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(baseIteratee)); return baseRest(function(args) { var thisArg = this; return arrayFunc(iteratees, function(iteratee) { diff --git a/_deburrLetter.js b/_deburrLetter.js index 153d6736c..0e31736be 100644 --- a/_deburrLetter.js +++ b/_deburrLetter.js @@ -55,7 +55,7 @@ define(['./_basePropertyOf'], function(basePropertyOf) { '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', '\u0132': 'IJ', '\u0133': 'ij', '\u0152': 'Oe', '\u0153': 'oe', - '\u0149': "'n", '\u017f': 'ss' + '\u0149': "'n", '\u017f': 's' }; /** diff --git a/_defineProperty.js b/_defineProperty.js deleted file mode 100644 index 51d1ba1cf..000000000 --- a/_defineProperty.js +++ /dev/null @@ -1,15 +0,0 @@ -define(['./_getNative'], function(getNative) { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; - - /* Used to set `toString` methods. */ - var defineProperty = (function() { - var func = getNative(Object, 'defineProperty'), - name = getNative.name; - - return (name && name.length > 2) ? func : undefined; - }()); - - return defineProperty; -}); diff --git a/_equalArrays.js b/_equalArrays.js index c67d2fc85..5bfcd381b 100644 --- a/_equalArrays.js +++ b/_equalArrays.js @@ -1,4 +1,4 @@ -define(['./_SetCache', './_arraySome'], function(SetCache, arraySome) { +define(['./_SetCache', './_arraySome', './_cacheHas'], function(SetCache, arraySome, cacheHas) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -61,9 +61,9 @@ define(['./_SetCache', './_arraySome'], function(SetCache, arraySome) { // Recursively compare arrays (susceptible to call stack limits). if (seen) { if (!arraySome(other, function(othValue, othIndex) { - if (!seen.has(othIndex) && + if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { - return seen.add(othIndex); + return seen.push(othIndex); } })) { result = false; diff --git a/_escapeHtmlChar.js b/_escapeHtmlChar.js index 7dd9b4644..c7d578321 100644 --- a/_escapeHtmlChar.js +++ b/_escapeHtmlChar.js @@ -6,8 +6,7 @@ define(['./_basePropertyOf'], function(basePropertyOf) { '<': '<', '>': '>', '"': '"', - "'": ''', - '`': '`' + "'": ''' }; /** diff --git a/_flatRest.js b/_flatRest.js new file mode 100644 index 000000000..578eb3497 --- /dev/null +++ b/_flatRest.js @@ -0,0 +1,18 @@ +define(['./flatten', './_overRest', './_setToString'], function(flatten, overRest, setToString) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + return flatRest; +}); diff --git a/_getTag.js b/_getTag.js index 5abc24cf7..8abd7d207 100644 --- a/_getTag.js +++ b/_getTag.js @@ -38,8 +38,7 @@ define(['./_DataView', './_Map', './_Promise', './_Set', './_WeakMap', './_baseG */ var 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. + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || diff --git a/_hasPath.js b/_hasPath.js index 81556dbe1..c774a6daa 100644 --- a/_hasPath.js +++ b/_hasPath.js @@ -12,9 +12,9 @@ define(['./_castPath', './isArguments', './isArray', './_isIndex', './_isKey', ' function hasPath(object, path, hasFunc) { path = isKey(path, object) ? [path] : castPath(path); - var result, - index = -1, - length = path.length; + var index = -1, + length = path.length, + result = false; while (++index < length) { var key = toKey(path[index]); @@ -23,10 +23,10 @@ define(['./_castPath', './isArguments', './isArray', './_isIndex', './_isKey', ' } object = object[key]; } - if (result) { + if (result || ++index != length) { return result; } - var length = object ? object.length : 0; + length = object ? object.length : 0; return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)); } diff --git a/_hashClear.js b/_hashClear.js index c6f08670f..4f9016e3d 100644 --- a/_hashClear.js +++ b/_hashClear.js @@ -9,6 +9,7 @@ define(['./_nativeCreate'], function(nativeCreate) { */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; } return hashClear; diff --git a/_hashDelete.js b/_hashDelete.js index abe75efc1..1a02f0618 100644 --- a/_hashDelete.js +++ b/_hashDelete.js @@ -11,7 +11,9 @@ define([], function() { * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { - return this.has(key) && delete this.__data__[key]; + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; } return hashDelete; diff --git a/_hashSet.js b/_hashSet.js index a85f38e07..4d49cfbcc 100644 --- a/_hashSet.js +++ b/_hashSet.js @@ -18,6 +18,7 @@ define(['./_nativeCreate'], function(nativeCreate) { */ function hashSet(key, value) { var data = this.__data__; + this.size += this.has(key) ? 0 : 1; data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; return this; } diff --git a/_insertWrapDetails.js b/_insertWrapDetails.js index 491577d26..01c742f84 100644 --- a/_insertWrapDetails.js +++ b/_insertWrapDetails.js @@ -12,9 +12,11 @@ define([], function() { * @returns {string} Returns the modified source. */ function insertWrapDetails(source, details) { - var length = details.length, - lastIndex = length - 1; - + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; details = details.join(length > 2 ? ', ' : ' '); return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); diff --git a/_isHostObject.js b/_isHostObject.js deleted file mode 100644 index dbc6c704e..000000000 --- a/_isHostObject.js +++ /dev/null @@ -1,23 +0,0 @@ -define([], function() { - - /** - * 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. - var result = false; - if (value != null && typeof value.toString != 'function') { - try { - result = !!(value + ''); - } catch (e) {} - } - return result; - } - - return isHostObject; -}); diff --git a/_listCacheClear.js b/_listCacheClear.js index 1ef079ec7..2a93166a3 100644 --- a/_listCacheClear.js +++ b/_listCacheClear.js @@ -9,6 +9,7 @@ define([], function() { */ function listCacheClear() { this.__data__ = []; + this.size = 0; } return listCacheClear; diff --git a/_listCacheDelete.js b/_listCacheDelete.js index fd9a4549c..45ebc443f 100644 --- a/_listCacheDelete.js +++ b/_listCacheDelete.js @@ -28,6 +28,7 @@ define(['./_assocIndexOf'], function(assocIndexOf) { } else { splice.call(data, index, 1); } + --this.size; return true; } diff --git a/_listCacheSet.js b/_listCacheSet.js index 59a9e4d97..7df66a11f 100644 --- a/_listCacheSet.js +++ b/_listCacheSet.js @@ -15,6 +15,7 @@ define(['./_assocIndexOf'], function(assocIndexOf) { index = assocIndexOf(data, key); if (index < 0) { + ++this.size; data.push([key, value]); } else { data[index][1] = value; diff --git a/_mapCacheClear.js b/_mapCacheClear.js index 6ba90923d..e91b64f47 100644 --- a/_mapCacheClear.js +++ b/_mapCacheClear.js @@ -8,6 +8,7 @@ define(['./_Hash', './_ListCache', './_Map'], function(Hash, ListCache, Map) { * @memberOf MapCache */ function mapCacheClear() { + this.size = 0; this.__data__ = { 'hash': new Hash, 'map': new (Map || ListCache), diff --git a/_mapCacheDelete.js b/_mapCacheDelete.js index 32dac7129..e4fb8d3fa 100644 --- a/_mapCacheDelete.js +++ b/_mapCacheDelete.js @@ -10,7 +10,9 @@ define(['./_getMapData'], function(getMapData) { * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { - return getMapData(this, key)['delete'](key); + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; } return mapCacheDelete; diff --git a/_mapCacheSet.js b/_mapCacheSet.js index 712bbfa8f..baf5282ce 100644 --- a/_mapCacheSet.js +++ b/_mapCacheSet.js @@ -11,7 +11,11 @@ define(['./_getMapData'], function(getMapData) { * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { - getMapData(this, key).set(key, value); + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; return this; } diff --git a/_memoizeCapped.js b/_memoizeCapped.js new file mode 100644 index 000000000..46f47fd81 --- /dev/null +++ b/_memoizeCapped.js @@ -0,0 +1,27 @@ +define(['./memoize'], function(memoize) { + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + return memoizeCapped; +}); diff --git a/_nativeDefineProperty.js b/_nativeDefineProperty.js new file mode 100644 index 000000000..638fa9853 --- /dev/null +++ b/_nativeDefineProperty.js @@ -0,0 +1,7 @@ +define(['./_getNative'], function(getNative) { + + /* Built-in method references that are verified to be native. */ + var nativeDefineProperty = getNative(Object, 'defineProperty'); + + return nativeDefineProperty; +}); diff --git a/_overRest.js b/_overRest.js new file mode 100644 index 000000000..ce7713943 --- /dev/null +++ b/_overRest.js @@ -0,0 +1,40 @@ +define(['./_apply'], function(apply) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax = Math.max; + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + return overRest; +}); diff --git a/_setData.js b/_setData.js index fe6d75317..1df650bb1 100644 --- a/_setData.js +++ b/_setData.js @@ -1,8 +1,4 @@ -define(['./_baseSetData', './now'], function(baseSetData, now) { - - /** Used to detect hot functions by number of calls within a span of milliseconds. */ - var HOT_COUNT = 150, - HOT_SPAN = 16; +define(['./_baseSetData', './_shortOut'], function(baseSetData, shortOut) { /** * Sets metadata for `func`. @@ -18,25 +14,7 @@ define(['./_baseSetData', './now'], function(baseSetData, now) { * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = (function() { - var count = 0, - lastCalled = 0; - - return function(key, value) { - var stamp = now(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return key; - } - } else { - count = 0; - } - return baseSetData(key, value); - }; - }()); + var setData = shortOut(baseSetData); return setData; }); diff --git a/_setToString.js b/_setToString.js new file mode 100644 index 000000000..f4971f2d6 --- /dev/null +++ b/_setToString.js @@ -0,0 +1,14 @@ +define(['./_baseSetToString', './_shortOut'], function(baseSetToString, shortOut) { + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + return setToString; +}); diff --git a/_setWrapToString.js b/_setWrapToString.js index 07d8951ca..d18c6a013 100644 --- a/_setWrapToString.js +++ b/_setWrapToString.js @@ -1,4 +1,4 @@ -define(['./constant', './_defineProperty', './_getWrapDetails', './identity', './_insertWrapDetails', './_updateWrapDetails'], function(constant, defineProperty, getWrapDetails, identity, insertWrapDetails, updateWrapDetails) { +define(['./_getWrapDetails', './_insertWrapDetails', './_setToString', './_updateWrapDetails'], function(getWrapDetails, insertWrapDetails, setToString, updateWrapDetails) { /** * Sets the `toString` method of `wrapper` to mimic the source of `reference` @@ -10,14 +10,10 @@ define(['./constant', './_defineProperty', './_getWrapDetails', './identity', '. * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @returns {Function} Returns `wrapper`. */ - var setWrapToString = !defineProperty ? identity : function(wrapper, reference, bitmask) { + function setWrapToString(wrapper, reference, bitmask) { var source = (reference + ''); - return defineProperty(wrapper, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))) - }); - }; + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } return setWrapToString; }); diff --git a/_shortOut.js b/_shortOut.js new file mode 100644 index 000000000..e02d9ce5a --- /dev/null +++ b/_shortOut.js @@ -0,0 +1,43 @@ +define([], function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 500, + HOT_SPAN = 16; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeNow = Date.now; + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + return shortOut; +}); diff --git a/_shuffleSelf.js b/_shuffleSelf.js new file mode 100644 index 000000000..7bcc41317 --- /dev/null +++ b/_shuffleSelf.js @@ -0,0 +1,26 @@ +define(['./_baseRandom'], function(baseRandom) { + + /** + * A specialized version of `arrayShuffle` which mutates `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + while (++index < length) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + return array; + } + + return shuffleSelf; +}); diff --git a/_stackClear.js b/_stackClear.js index 49a436f02..bc571f14c 100644 --- a/_stackClear.js +++ b/_stackClear.js @@ -9,6 +9,7 @@ define(['./_ListCache'], function(ListCache) { */ function stackClear() { this.__data__ = new ListCache; + this.size = 0; } return stackClear; diff --git a/_stackDelete.js b/_stackDelete.js index a90e9161c..e93dc1324 100644 --- a/_stackDelete.js +++ b/_stackDelete.js @@ -10,7 +10,11 @@ define([], function() { * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { - return this.__data__['delete'](key); + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; } return stackDelete; diff --git a/_stackSet.js b/_stackSet.js index 8ee7616bc..3fc266cf8 100644 --- a/_stackSet.js +++ b/_stackSet.js @@ -14,16 +14,18 @@ define(['./_ListCache', './_Map', './_MapCache'], function(ListCache, Map, MapCa * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { - var cache = this.__data__; - if (cache instanceof ListCache) { - var pairs = cache.__data__; + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { pairs.push([key, value]); + this.size = ++data.size; return this; } - cache = this.__data__ = new MapCache(pairs); + data = this.__data__ = new MapCache(pairs); } - cache.set(key, value); + data.set(key, value); + this.size = data.size; return this; } diff --git a/_strictIndexOf.js b/_strictIndexOf.js new file mode 100644 index 000000000..f3853e468 --- /dev/null +++ b/_strictIndexOf.js @@ -0,0 +1,26 @@ +define([], function() { + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + return strictIndexOf; +}); diff --git a/_strictLastIndexOf.js b/_strictLastIndexOf.js new file mode 100644 index 000000000..bc6561cf3 --- /dev/null +++ b/_strictLastIndexOf.js @@ -0,0 +1,24 @@ +define([], function() { + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + return strictLastIndexOf; +}); diff --git a/_stringToPath.js b/_stringToPath.js index 19af02d13..2ffcd1188 100644 --- a/_stringToPath.js +++ b/_stringToPath.js @@ -1,4 +1,4 @@ -define(['./memoize', './toString'], function(memoize, toString) { +define(['./_memoizeCapped', './toString'], function(memoizeCapped, toString) { /** Used to match property names within property paths. */ var reLeadingDot = /^\./, @@ -14,7 +14,7 @@ define(['./memoize', './toString'], function(memoize, toString) { * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ - var stringToPath = memoize(function(string) { + var stringToPath = memoizeCapped(function(string) { string = toString(string); var result = []; diff --git a/_unescapeHtmlChar.js b/_unescapeHtmlChar.js index 4bea17471..2bd48363b 100644 --- a/_unescapeHtmlChar.js +++ b/_unescapeHtmlChar.js @@ -6,8 +6,7 @@ define(['./_basePropertyOf'], function(basePropertyOf) { '<': '<', '>': '>', '"': '"', - ''': "'", - '`': '`' + ''': "'" }; /** diff --git a/_unicodeSize.js b/_unicodeSize.js index 90a590e2e..166d412b8 100644 --- a/_unicodeSize.js +++ b/_unicodeSize.js @@ -36,7 +36,7 @@ define([], function() { function unicodeSize(string) { var result = reUnicode.lastIndex = 0; while (reUnicode.test(string)) { - result++; + ++result; } return result; } diff --git a/assign.js b/assign.js index 47f495bb4..cfcfa8512 100644 --- a/assign.js +++ b/assign.js @@ -6,12 +6,6 @@ define(['./_assignValue', './_copyObject', './_createAssigner', './isArrayLike', /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; - /** Built-in value references. */ - var propertyIsEnumerable = objectProto.propertyIsEnumerable; - - /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ - var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); - /** * Assigns own enumerable string keyed properties of source objects to the * destination object. Source objects are applied from left to right. @@ -45,7 +39,7 @@ define(['./_assignValue', './_copyObject', './_createAssigner', './isArrayLike', * // => { 'a': 1, 'c': 3 } */ var assign = createAssigner(function(object, source) { - if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { + if (isPrototype(source) || isArrayLike(source)) { copyObject(source, keys(source), object); return; } diff --git a/at.js b/at.js index 62e894f88..fa34f44d6 100644 --- a/at.js +++ b/at.js @@ -1,4 +1,4 @@ -define(['./_baseAt', './_baseFlatten', './_baseRest'], function(baseAt, baseFlatten, baseRest) { +define(['./_baseAt', './_flatRest'], function(baseAt, flatRest) { /** * Creates an array of values corresponding to `paths` of `object`. @@ -17,9 +17,7 @@ define(['./_baseAt', './_baseFlatten', './_baseRest'], function(baseAt, baseFlat * _.at(object, ['a[0].b.c', 'a[1]']); * // => [3, 4] */ - var at = baseRest(function(object, paths) { - return baseAt(object, baseFlatten(paths, 1)); - }); + var at = flatRest(baseAt); return at; }); diff --git a/bindAll.js b/bindAll.js index 4c04a1e52..59fd79036 100644 --- a/bindAll.js +++ b/bindAll.js @@ -1,4 +1,4 @@ -define(['./_arrayEach', './_baseFlatten', './_baseRest', './bind', './_toKey'], function(arrayEach, baseFlatten, baseRest, bind, toKey) { +define(['./_arrayEach', './_baseAssignValue', './bind', './_flatRest', './_toKey'], function(arrayEach, baseAssignValue, bind, flatRest, toKey) { /** * Binds methods of an object to the object itself, overwriting the existing @@ -26,10 +26,10 @@ define(['./_arrayEach', './_baseFlatten', './_baseRest', './bind', './_toKey'], * jQuery(element).on('click', view.click); * // => Logs 'clicked docs' when clicked. */ - var bindAll = baseRest(function(object, methodNames) { - arrayEach(baseFlatten(methodNames, 1), function(key) { + var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { key = toKey(key); - object[key] = bind(object[key], object); + baseAssignValue(object, key, bind(object[key], object)); }); return object; }); diff --git a/concat.js b/concat.js index 38293c7d7..5c35ab8df 100644 --- a/concat.js +++ b/concat.js @@ -23,17 +23,18 @@ define(['./_arrayPush', './_baseFlatten', './_copyArray', './isArray'], function * // => [1] */ function concat() { - var length = arguments.length, - args = Array(length ? length - 1 : 0), + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), array = arguments[0], index = length; while (index--) { args[index - 1] = arguments[index]; } - return length - ? arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)) - : []; + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); } return concat; diff --git a/countBy.js b/countBy.js index a1473b820..dc0967d5d 100644 --- a/countBy.js +++ b/countBy.js @@ -1,4 +1,4 @@ -define(['./_createAggregator'], function(createAggregator) { +define(['./_baseAssignValue', './_createAggregator'], function(baseAssignValue, createAggregator) { /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -30,7 +30,11 @@ define(['./_createAggregator'], function(createAggregator) { * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { - hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } }); return countBy; diff --git a/defer.js b/defer.js index f65ec31f6..81c46c165 100644 --- a/defer.js +++ b/defer.js @@ -16,7 +16,7 @@ define(['./_baseDelay', './_baseRest'], function(baseDelay, baseRest) { * _.defer(function(text) { * console.log(text); * }, 'deferred'); - * // => Logs 'deferred' after one or more milliseconds. + * // => Logs 'deferred' after one millisecond. */ var defer = baseRest(function(func, args) { return baseDelay(func, 1, args); diff --git a/difference.js b/difference.js index c5cdf9614..d566aec92 100644 --- a/difference.js +++ b/difference.js @@ -3,8 +3,8 @@ define(['./_baseDifference', './_baseFlatten', './_baseRest', './isArrayLikeObje /** * Creates an array of `array` values not included in the other given arrays * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order of result values is determined by the - * order they occur in the first array. + * for equality comparisons. The order and references of result values are + * determined by the first array. * * **Note:** Unlike `_.pullAll`, this method returns a new array. * diff --git a/differenceBy.js b/differenceBy.js index 416092e3d..1dfeb07e0 100644 --- a/differenceBy.js +++ b/differenceBy.js @@ -6,8 +6,9 @@ define(['./_baseDifference', './_baseFlatten', './_baseIteratee', './_baseRest', /** * This method is like `_.difference` except that it accepts `iteratee` which * is invoked for each element of `array` and `values` to generate the criterion - * by which they're compared. Result values are chosen from the first array. - * The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). * * **Note:** Unlike `_.pullAllBy`, this method returns a new array. * diff --git a/differenceWith.js b/differenceWith.js index 40f8719f9..b3953d620 100644 --- a/differenceWith.js +++ b/differenceWith.js @@ -5,9 +5,9 @@ define(['./_baseDifference', './_baseFlatten', './_baseRest', './isArrayLikeObje /** * This method is like `_.difference` except that it accepts `comparator` - * which is invoked to compare elements of `array` to `values`. Result values - * are chosen from the first array. The comparator is invoked with two arguments: - * (arrVal, othVal). + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). * * **Note:** Unlike `_.pullAllWith`, this method returns a new array. * diff --git a/escape.js b/escape.js index 23a24b900..2b25517ba 100644 --- a/escape.js +++ b/escape.js @@ -5,8 +5,8 @@ define(['./_escapeHtmlChar', './toString'], function(escapeHtmlChar, toString) { reHasUnescapedHtml = RegExp(reUnescapedHtml.source); /** - * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to - * their corresponding HTML entities. + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional * characters use a third-party library like [_he_](https://mths.be/he). @@ -17,12 +17,6 @@ define(['./_escapeHtmlChar', './toString'], function(escapeHtmlChar, toString) { * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * - * Backticks are escaped because in IE < 9, they can break out of - * attribute values or HTML comments. See [#59](https://html5sec.org/#59), - * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and - * [#133](https://html5sec.org/#133) of the - * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. - * * When working with HTML you should always * [quote attribute values](http://wonko.com/post/html-escaping) to reduce * XSS vectors. diff --git a/forEach.js b/forEach.js index 65f39f9fe..9b9615104 100644 --- a/forEach.js +++ b/forEach.js @@ -20,7 +20,7 @@ define(['./_arrayEach', './_baseEach', './_baseIteratee', './isArray'], function * @see _.forEachRight * @example * - * _([1, 2]).forEach(function(value) { + * _.forEach([1, 2], function(value) { * console.log(value); * }); * // => Logs `1` then `2`. diff --git a/groupBy.js b/groupBy.js index fc930bb46..89fc80082 100644 --- a/groupBy.js +++ b/groupBy.js @@ -1,4 +1,4 @@ -define(['./_createAggregator'], function(createAggregator) { +define(['./_baseAssignValue', './_createAggregator'], function(baseAssignValue, createAggregator) { /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -34,7 +34,7 @@ define(['./_createAggregator'], function(createAggregator) { if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { - result[key] = [value]; + baseAssignValue(result, key, [value]); } }); diff --git a/intersection.js b/intersection.js index ae21fefa8..074f6ad67 100644 --- a/intersection.js +++ b/intersection.js @@ -3,8 +3,8 @@ define(['./_arrayMap', './_baseIntersection', './_baseRest', './_castArrayLikeOb /** * Creates an array of unique values that are included in all given arrays * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order of result values is determined by the - * order they occur in the first array. + * for equality comparisons. The order and references of result values are + * determined by the first array. * * @static * @memberOf _ diff --git a/intersectionBy.js b/intersectionBy.js index 28caa5285..3d2145e71 100644 --- a/intersectionBy.js +++ b/intersectionBy.js @@ -6,8 +6,9 @@ define(['./_arrayMap', './_baseIntersection', './_baseIteratee', './_baseRest', /** * This method is like `_.intersection` except that it accepts `iteratee` * which is invoked for each element of each `arrays` to generate the criterion - * by which they're compared. Result values are chosen from the first array. - * The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ diff --git a/intersectionWith.js b/intersectionWith.js index 6f3dfcfa9..6b8293631 100644 --- a/intersectionWith.js +++ b/intersectionWith.js @@ -5,9 +5,9 @@ define(['./_arrayMap', './_baseIntersection', './_baseRest', './_castArrayLikeOb /** * This method is like `_.intersection` except that it accepts `comparator` - * which is invoked to compare elements of `arrays`. Result values are chosen - * from the first array. The comparator is invoked with two arguments: - * (arrVal, othVal). + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). * * @static * @memberOf _ diff --git a/isElement.js b/isElement.js index a801d56ec..4258d6507 100644 --- a/isElement.js +++ b/isElement.js @@ -18,7 +18,7 @@ define(['./isObjectLike', './isPlainObject'], function(isObjectLike, isPlainObje * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + return value != null && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } return isElement; diff --git a/isEmpty.js b/isEmpty.js index d534d0b94..a8d3c8260 100644 --- a/isEmpty.js +++ b/isEmpty.js @@ -10,12 +10,6 @@ define(['./_getTag', './isArguments', './isArray', './isArrayLike', './isBuffer' /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; - /** Built-in value references. */ - var propertyIsEnumerable = objectProto.propertyIsEnumerable; - - /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ - var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); - /** * Checks if `value` is an empty object, collection, map, or set. * @@ -59,7 +53,7 @@ define(['./_getTag', './isArguments', './isArray', './isArrayLike', './isBuffer' if (tag == mapTag || tag == setTag) { return !value.size; } - if (nonEnumShadows || isPrototype(value)) { + if (isPrototype(value)) { return !nativeKeys(value).length; } for (var key in value) { diff --git a/isObject.js b/isObject.js index 5480483df..a3d180ee2 100644 --- a/isObject.js +++ b/isObject.js @@ -27,7 +27,7 @@ define([], function() { */ function isObject(value) { var type = typeof value; - return !!value && (type == 'object' || type == 'function'); + return value != null && (type == 'object' || type == 'function'); } return isObject; diff --git a/isObjectLike.js b/isObjectLike.js index bfa102ec6..10753faec 100644 --- a/isObjectLike.js +++ b/isObjectLike.js @@ -25,7 +25,7 @@ define([], function() { * // => false */ function isObjectLike(value) { - return !!value && typeof value == 'object'; + return value != null && typeof value == 'object'; } return isObjectLike; diff --git a/isPlainObject.js b/isPlainObject.js index 24d53787a..b512bf0ea 100644 --- a/isPlainObject.js +++ b/isPlainObject.js @@ -1,4 +1,4 @@ -define(['./_getPrototype', './_isHostObject', './isObjectLike'], function(getPrototype, isHostObject, isObjectLike) { +define(['./_getPrototype', './isObjectLike'], function(getPrototype, isObjectLike) { /** `Object#toString` result references. */ var objectTag = '[object Object]'; @@ -52,8 +52,7 @@ define(['./_getPrototype', './_isHostObject', './isObjectLike'], function(getPro * // => true */ function isPlainObject(value) { - if (!isObjectLike(value) || - objectToString.call(value) != objectTag || isHostObject(value)) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag) { return false; } var proto = getPrototype(value); diff --git a/keyBy.js b/keyBy.js index dc2496676..e22907a2e 100644 --- a/keyBy.js +++ b/keyBy.js @@ -1,4 +1,4 @@ -define(['./_createAggregator'], function(createAggregator) { +define(['./_baseAssignValue', './_createAggregator'], function(baseAssignValue, createAggregator) { /** * Creates an object composed of keys generated from the results of running @@ -30,7 +30,7 @@ define(['./_createAggregator'], function(createAggregator) { * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { - result[key] = value; + baseAssignValue(result, key, value); }); return keyBy; diff --git a/lastIndexOf.js b/lastIndexOf.js index 7cf8f226c..a967b20dc 100644 --- a/lastIndexOf.js +++ b/lastIndexOf.js @@ -1,4 +1,4 @@ -define(['./_baseFindIndex', './_baseIsNaN', './toInteger'], function(baseFindIndex, baseIsNaN, toInteger) { +define(['./_baseFindIndex', './_baseIsNaN', './_strictLastIndexOf', './toInteger'], function(baseFindIndex, baseIsNaN, strictLastIndexOf, toInteger) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -36,21 +36,11 @@ define(['./_baseFindIndex', './_baseIsNaN', './toInteger'], function(baseFindInd var index = length; if (fromIndex !== undefined) { index = toInteger(fromIndex); - index = ( - index < 0 - ? nativeMax(length + index, 0) - : nativeMin(index, length - 1) - ) + 1; + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); } - if (value !== value) { - return baseFindIndex(array, baseIsNaN, index - 1, true); - } - while (index--) { - if (array[index] === value) { - return index; - } - } - return -1; + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); } return lastIndexOf; diff --git a/main.js b/main.js index a793fc27c..270840b86 100644 --- a/main.js +++ b/main.js @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.15.0'; + var VERSION = '4.16.0'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -24,6 +24,9 @@ /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = '__lodash_hash_undefined__'; + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; @@ -48,7 +51,7 @@ DEFAULT_TRUNC_OMISSION = '...'; /** Used to detect hot functions by number of calls within a span of milliseconds. */ - var HOT_COUNT = 150, + var HOT_COUNT = 500, HOT_SPAN = 16; /** Used to indicate the type of lazy iteratees. */ @@ -165,9 +168,6 @@ /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; - /** Used to detect hexadecimal string values. */ - var reHasHexPrefix = /^0x/i; - /** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; @@ -362,7 +362,7 @@ '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', '\u0132': 'IJ', '\u0133': 'ij', '\u0152': 'Oe', '\u0153': 'oe', - '\u0149': "'n", '\u017f': 'ss' + '\u0149': "'n", '\u017f': 's' }; /** Used to map characters to HTML entities. */ @@ -371,8 +371,7 @@ '<': '<', '>': '>', '"': '"', - "'": ''', - '`': '`' + "'": ''' }; /** Used to map HTML entities to characters. */ @@ -381,8 +380,7 @@ '<': '<', '>': '>', '"': '"', - ''': "'", - '`': '`' + ''': "'" }; /** Used to escape characters for inclusion in compiled string literals. */ @@ -823,18 +821,9 @@ * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { - if (value !== value) { - return baseFindIndex(array, baseIsNaN, fromIndex); - } - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); } /** @@ -1039,7 +1028,7 @@ } /** - * Checks if a cache value for `key` exists. + * Checks if a `cache` value for `key` exists. * * @private * @param {Object} cache The cache to query. @@ -1097,7 +1086,7 @@ while (length--) { if (array[length] === placeholder) { - result++; + ++result; } } return result; @@ -1167,25 +1156,6 @@ return reHasUnicodeWord.test(string); } - /** - * 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. - var result = false; - if (value != null && typeof value.toString != 'function') { - try { - result = !!(value + ''); - } catch (e) {} - } - return result; - } - /** * Converts `iterator` to an array. * @@ -1293,6 +1263,48 @@ return result; } + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + /** * Gets the number of symbols in `string`. * @@ -1338,7 +1350,7 @@ function unicodeSize(string) { var result = reUnicode.lastIndex = 0; while (reUnicode.test(string)) { - result++; + ++result; } return result; } @@ -1393,13 +1405,6 @@ * lodash.isFunction(lodash.bar); * // => true * - * // Use `context` to stub `Date#getTime` use in `_.now`. - * var stubbed = _.runInContext({ - * 'Date': function() { - * return { 'getTime': stubGetTime }; - * } - * }); - * * // Create a suped-up `defer` in Node.js. * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ @@ -1463,6 +1468,7 @@ var Buffer = moduleExports ? context.Buffer : undefined, Symbol = context.Symbol, Uint8Array = context.Uint8Array, + defineProperty = Object.defineProperty, getPrototype = overArg(Object.getPrototypeOf, Object), iteratorSymbol = Symbol ? Symbol.iterator : undefined, objectCreate = Object.create, @@ -1485,6 +1491,7 @@ nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeMin = Math.min, + nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReverse = arrayProto.reverse; @@ -1495,22 +1502,12 @@ Promise = getNative(context, 'Promise'), Set = getNative(context, 'Set'), WeakMap = getNative(context, 'WeakMap'), - nativeCreate = getNative(Object, 'create'); - - /* Used to set `toString` methods. */ - var defineProperty = (function() { - var func = getNative(Object, 'defineProperty'), - name = getNative.name; - - return (name && name.length > 2) ? func : undefined; - }()); + nativeCreate = getNative(Object, 'create'), + nativeDefineProperty = getNative(Object, 'defineProperty'); /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; - /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ - var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); - /** Used to lookup unminified function names. */ var realNames = {}; @@ -1898,6 +1895,7 @@ */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; } /** @@ -1911,7 +1909,9 @@ * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { - return this.has(key) && delete this.__data__[key]; + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; } /** @@ -1958,6 +1958,7 @@ */ function hashSet(key, value) { var data = this.__data__; + this.size += this.has(key) ? 0 : 1; data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; return this; } @@ -1998,6 +1999,7 @@ */ function listCacheClear() { this.__data__ = []; + this.size = 0; } /** @@ -2022,6 +2024,7 @@ } else { splice.call(data, index, 1); } + --this.size; return true; } @@ -2069,6 +2072,7 @@ index = assocIndexOf(data, key); if (index < 0) { + ++this.size; data.push([key, value]); } else { data[index][1] = value; @@ -2111,6 +2115,7 @@ * @memberOf MapCache */ function mapCacheClear() { + this.size = 0; this.__data__ = { 'hash': new Hash, 'map': new (Map || ListCache), @@ -2128,7 +2133,9 @@ * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { - return getMapData(this, key)['delete'](key); + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; } /** @@ -2168,7 +2175,11 @@ * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { - getMapData(this, key).set(key, value); + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; return this; } @@ -2241,7 +2252,8 @@ * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { - this.__data__ = new ListCache(entries); + var data = this.__data__ = new ListCache(entries); + this.size = data.size; } /** @@ -2253,6 +2265,7 @@ */ function stackClear() { this.__data__ = new ListCache; + this.size = 0; } /** @@ -2265,7 +2278,11 @@ * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { - return this.__data__['delete'](key); + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; } /** @@ -2305,16 +2322,18 @@ * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { - var cache = this.__data__; - if (cache instanceof ListCache) { - var pairs = cache.__data__; + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { pairs.push([key, value]); + this.size = ++data.size; return this; } - cache = this.__data__ = new MapCache(pairs); + data = this.__data__ = new MapCache(pairs); } - cache.set(key, value); + data.set(key, value); + this.size = data.size; return this; } @@ -2354,6 +2373,44 @@ return result; } + /** + * A specialized version of `_.sample` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + var result = arrayShuffle(array); + result.length = baseClamp(n, 0, result.length); + return result; + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + /** * Used by `_.defaults` to customize its `_.assignIn` use. * @@ -2384,7 +2441,7 @@ function assignMergeValue(object, key, value) { if ((value !== undefined && !eq(object[key], value)) || (typeof key == 'number' && value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); } } @@ -2402,7 +2459,7 @@ var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { - object[key] = value; + baseAssignValue(object, key, value); } } @@ -2455,6 +2512,28 @@ return object && copyObject(source, keys(source), object); } + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + /** * The base implementation of `_.at` without support for individual paths. * @@ -2535,9 +2614,6 @@ return cloneBuffer(value, isDeep); } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { - if (isHostObject(value)) { - return object ? value : {}; - } result = initCloneObject(isFunc ? {} : value); if (!isDeep) { return copySymbols(value, baseAssign(result, value)); @@ -3181,8 +3257,8 @@ othTag = getTag(other); othTag = othTag == argsTag ? objectTag : othTag; } - var objIsObj = objTag == objectTag && !isHostObject(object), - othIsObj = othTag == objectTag && !isHostObject(other), + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, isSameTag = objTag == othTag; if (isSameTag && !objIsObj) { @@ -3287,7 +3363,7 @@ if (!isObject(value) || isMasked(value)) { return false; } - var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; return pattern.test(toSource(value)); } @@ -3645,7 +3721,7 @@ value = object[key]; if (predicate(value, key)) { - result[key] = value; + baseAssignValue(result, key, value); } } return result; @@ -3811,24 +3887,7 @@ * @returns {Function} Returns the new function. */ function baseRest(func, start) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = array; - return apply(func, this, otherArgs); - }; + return setToString(overRest(func, start, identity), func + ''); } /** @@ -3872,7 +3931,7 @@ } /** - * The base implementation of `setData` without support for hot loop detection. + * The base implementation of `setData` without support for hot loop shorting. * * @private * @param {Function} func The function to associate metadata with. @@ -3884,6 +3943,23 @@ return func; }; + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !nativeDefineProperty ? identity : function(func, string) { + return nativeDefineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + /** * The base implementation of `_.slice` without an iteratee call guard. * @@ -4298,6 +4374,17 @@ return isArray(value) ? value : stringToPath(value); } + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + /** * Casts `array` to a slice if it's needed. * @@ -4612,6 +4699,7 @@ * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { + var isNew = !object; object || (object = {}); var index = -1, @@ -4624,7 +4712,14 @@ ? customizer(object[key], source[key], key, object, source) : undefined; - assignValue(object, key, newValue === undefined ? source[key] : newValue); + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } } return object; } @@ -4903,9 +4998,7 @@ * @returns {Function} Returns the new flow function. */ function createFlow(fromRight) { - return baseRest(function(funcs) { - funcs = baseFlatten(funcs, 1); - + return flatRest(function(funcs) { var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; @@ -5088,11 +5181,8 @@ * @returns {Function} Returns the new over function. */ function createOver(arrayFunc) { - return baseRest(function(iteratees) { - iteratees = (iteratees.length == 1 && isArray(iteratees[0])) - ? arrayMap(iteratees[0], baseUnary(getIteratee())) - : arrayMap(baseFlatten(iteratees, 1), baseUnary(getIteratee())); - + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); return baseRest(function(args) { var thisArg = this; return arrayFunc(iteratees, function(iteratee) { @@ -5435,9 +5525,9 @@ // Recursively compare arrays (susceptible to call stack limits). if (seen) { if (!arraySome(other, function(othValue, othIndex) { - if (!seen.has(othIndex) && + if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { - return seen.add(othIndex); + return seen.push(othIndex); } })) { result = false; @@ -5617,6 +5707,17 @@ return result; } + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + /** * Creates an array of own enumerable property names and symbols of `object`. * @@ -5785,8 +5886,7 @@ */ var 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. + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || @@ -5862,9 +5962,9 @@ function hasPath(object, path, hasFunc) { path = isKey(path, object) ? [path] : castPath(path); - var result, - index = -1, - length = path.length; + var index = -1, + length = path.length, + result = false; while (++index < length) { var key = toKey(path[index]); @@ -5873,10 +5973,10 @@ } object = object[key]; } - if (result) { + if (result || ++index != length) { return result; } - var length = object ? object.length : 0; + length = object ? object.length : 0; return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)); } @@ -5971,9 +6071,11 @@ * @returns {string} Returns the modified source. */ function insertWrapDetails(source, details) { - var length = details.length, - lastIndex = length - 1; - + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; details = details.join(length > 2 ? ', ' : ' '); return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); @@ -6152,6 +6254,26 @@ }; } + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + /** * Merges the function metadata of `source` into `data`. * @@ -6265,6 +6387,36 @@ return result; } + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + /** * Gets the parent value at `path` of `object`. * @@ -6313,25 +6465,7 @@ * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = (function() { - var count = 0, - lastCalled = 0; - - return function(key, value) { - var stamp = now(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return key; - } - } else { - count = 0; - } - return baseSetData(key, value); - }; - }()); + var setData = shortOut(baseSetData); /** * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). @@ -6345,6 +6479,16 @@ return root.setTimeout(func, wait); }; + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + /** * Sets the `toString` method of `wrapper` to mimic the source of `reference` * with wrapper details in a comment at the top of the source body. @@ -6355,14 +6499,61 @@ * @param {number} bitmask The bitmask flags. See `createWrap` for more details. * @returns {Function} Returns `wrapper`. */ - var setWrapToString = !defineProperty ? identity : function(wrapper, reference, bitmask) { + function setWrapToString(wrapper, reference, bitmask) { var source = (reference + ''); - return defineProperty(wrapper, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))) - }); - }; + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `arrayShuffle` which mutates `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + while (++index < length) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + return array; + } /** * Converts `string` to a property path array. @@ -6371,7 +6562,7 @@ * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ - var stringToPath = memoize(function(string) { + var stringToPath = memoizeCapped(function(string) { string = toString(string); var result = []; @@ -6550,24 +6741,25 @@ * // => [1] */ function concat() { - var length = arguments.length, - args = Array(length ? length - 1 : 0), + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), array = arguments[0], index = length; while (index--) { args[index - 1] = arguments[index]; } - return length - ? arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)) - : []; + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); } /** * Creates an array of `array` values not included in the other given arrays * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order of result values is determined by the - * order they occur in the first array. + * for equality comparisons. The order and references of result values are + * determined by the first array. * * **Note:** Unlike `_.pullAll`, this method returns a new array. * @@ -6593,8 +6785,9 @@ /** * This method is like `_.difference` except that it accepts `iteratee` which * is invoked for each element of `array` and `values` to generate the criterion - * by which they're compared. Result values are chosen from the first array. - * The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). * * **Note:** Unlike `_.pullAllBy`, this method returns a new array. * @@ -6627,9 +6820,9 @@ /** * This method is like `_.difference` except that it accepts `comparator` - * which is invoked to compare elements of `array` to `values`. Result values - * are chosen from the first array. The comparator is invoked with two arguments: - * (arrVal, othVal). + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). * * **Note:** Unlike `_.pullAllWith`, this method returns a new array. * @@ -7123,8 +7316,8 @@ /** * Creates an array of unique values that are included in all given arrays * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order of result values is determined by the - * order they occur in the first array. + * for equality comparisons. The order and references of result values are + * determined by the first array. * * @static * @memberOf _ @@ -7147,8 +7340,9 @@ /** * This method is like `_.intersection` except that it accepts `iteratee` * which is invoked for each element of each `arrays` to generate the criterion - * by which they're compared. Result values are chosen from the first array. - * The iteratee is invoked with one argument: (value). + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ @@ -7182,9 +7376,9 @@ /** * This method is like `_.intersection` except that it accepts `comparator` - * which is invoked to compare elements of `arrays`. Result values are chosen - * from the first array. The comparator is invoked with two arguments: - * (arrVal, othVal). + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). * * @static * @memberOf _ @@ -7282,21 +7476,11 @@ var index = length; if (fromIndex !== undefined) { index = toInteger(fromIndex); - index = ( - index < 0 - ? nativeMax(length + index, 0) - : nativeMin(index, length - 1) - ) + 1; + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); } - if (value !== value) { - return baseFindIndex(array, baseIsNaN, index - 1, true); - } - while (index--) { - if (array[index] === value) { - return index; - } - } - return -1; + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); } /** @@ -7458,9 +7642,7 @@ * console.log(pulled); * // => ['b', 'd'] */ - var pullAt = baseRest(function(array, indexes) { - indexes = baseFlatten(indexes, 1); - + var pullAt = flatRest(function(array, indexes) { var length = array ? array.length : 0, result = baseAt(array, indexes); @@ -8035,8 +8217,9 @@ /** * Creates a duplicate-free version of an array, using * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons, in which only the first occurrence of each - * element is kept. + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. * * @static * @memberOf _ @@ -8058,7 +8241,9 @@ /** * This method is like `_.uniq` except that it accepts `iteratee` which is * invoked for each element in `array` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ @@ -8085,8 +8270,9 @@ /** * This method is like `_.uniq` except that it accepts `comparator` which - * is invoked to compare elements of `array`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _ @@ -8228,8 +8414,9 @@ /** * This method is like `_.xor` except that it accepts `iteratee` which is * invoked for each element of each `arrays` to generate the criterion by - * which by which they're compared. The iteratee is invoked with one argument: - * (value). + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). * * @static * @memberOf _ @@ -8258,8 +8445,9 @@ /** * This method is like `_.xor` except that it accepts `comparator` which is - * invoked to compare elements of `arrays`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _ @@ -8476,8 +8664,7 @@ * _(object).at(['a[0].b.c', 'a[1]']).value(); * // => [3, 4] */ - var wrapperAt = baseRest(function(paths) { - paths = baseFlatten(paths, 1); + var wrapperAt = flatRest(function(paths) { var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, @@ -8742,7 +8929,11 @@ * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { - hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } }); /** @@ -8997,7 +9188,7 @@ * @see _.forEachRight * @example * - * _([1, 2]).forEach(function(value) { + * _.forEach([1, 2], function(value) { * console.log(value); * }); * // => Logs `1` then `2`. @@ -9065,7 +9256,7 @@ if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { - result[key] = [value]; + baseAssignValue(result, key, [value]); } }); @@ -9178,7 +9369,7 @@ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { - result[key] = value; + baseAssignValue(result, key, value); }); /** @@ -9438,10 +9629,7 @@ * // => 2 */ function sample(collection) { - var array = isArrayLike(collection) ? collection : values(collection), - length = array.length; - - return length > 0 ? array[baseRandom(0, length - 1)] : undefined; + return arraySample(isArrayLike(collection) ? collection : values(collection)); } /** @@ -9465,25 +9653,12 @@ * // => [2, 3, 1] */ function sampleSize(collection, n, guard) { - var index = -1, - result = toArray(collection), - length = result.length, - lastIndex = length - 1; - if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { n = 1; } else { - n = baseClamp(toInteger(n), 0, length); + n = toInteger(n); } - while (++index < n) { - var rand = baseRandom(index, lastIndex), - value = result[rand]; - - result[rand] = result[index]; - result[index] = value; - } - result.length = n; - return result; + return arraySampleSize(isArrayLike(collection) ? collection : values(collection), n); } /** @@ -9502,7 +9677,10 @@ * // => [4, 1, 3, 2] */ function shuffle(collection) { - return sampleSize(collection, MAX_ARRAY_LENGTH); + return shuffleSelf(isArrayLike(collection) + ? copyArray(collection) + : values(collection) + ); } /** @@ -9607,16 +9785,11 @@ * { 'user': 'barney', 'age': 34 } * ]; * - * _.sortBy(users, function(o) { return o.user; }); + * _.sortBy(users, [function(o) { return o.user; }]); * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] * * _.sortBy(users, ['user', 'age']); * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] - * - * _.sortBy(users, 'user', function(o) { - * return Math.floor(o.age / 10); - * }); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] */ var sortBy = baseRest(function(collection, iteratees) { if (collection == null) { @@ -10131,7 +10304,7 @@ * _.defer(function(text) { * console.log(text); * }, 'deferred'); - * // => Logs 'deferred' after one or more milliseconds. + * // => Logs 'deferred' after one millisecond. */ var defer = baseRest(function(func, args) { return baseDelay(func, 1, args); @@ -10239,14 +10412,14 @@ return cache.get(key); } var result = func.apply(this, args); - memoized.cache = cache.set(key, result); + memoized.cache = cache.set(key, result) || cache; return result; }; memoized.cache = new (memoize.Cache || MapCache); return memoized; } - // Assign cache to `_.memoize`. + // Expose `MapCache`. memoize.Cache = MapCache; /** @@ -10338,7 +10511,7 @@ * func(10, 5); * // => [100, 10] */ - var overArgs = baseRest(function(func, transforms) { + var overArgs = castRest(function(func, transforms) { transforms = (transforms.length == 1 && isArray(transforms[0])) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); @@ -10452,8 +10625,8 @@ * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] */ - var rearg = baseRest(function(func, indexes) { - return createWrap(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1)); + var rearg = flatRest(function(func, indexes) { + return createWrap(func, REARG_FLAG, undefined, undefined, undefined, indexes); }); /** @@ -11129,7 +11302,7 @@ * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + return value != null && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } /** @@ -11175,7 +11348,7 @@ if (tag == mapTag || tag == setTag) { return !value.size; } - if (nonEnumShadows || isPrototype(value)) { + if (isPrototype(value)) { return !nativeKeys(value).length; } for (var key in value) { @@ -11424,7 +11597,7 @@ */ function isObject(value) { var type = typeof value; - return !!value && (type == 'object' || type == 'function'); + return value != null && (type == 'object' || type == 'function'); } /** @@ -11452,7 +11625,7 @@ * // => false */ function isObjectLike(value) { - return !!value && typeof value == 'object'; + return value != null && typeof value == 'object'; } /** @@ -11716,8 +11889,7 @@ * // => true */ function isPlainObject(value) { - if (!isObjectLike(value) || - objectToString.call(value) != objectTag || isHostObject(value)) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag) { return false; } var proto = getPrototype(value); @@ -12274,7 +12446,7 @@ * // => { 'a': 1, 'c': 3 } */ var assign = createAssigner(function(object, source) { - if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { + if (isPrototype(source) || isArrayLike(source)) { copyObject(source, keys(source), object); return; } @@ -12402,9 +12574,7 @@ * _.at(object, ['a[0].b.c', 'a[1]']); * // => [3, 4] */ - var at = baseRest(function(object, paths) { - return baseAt(object, baseFlatten(paths, 1)); - }); + var at = flatRest(baseAt); /** * Creates an object that inherits from the `prototype` object. If a @@ -13007,7 +13177,7 @@ iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[iteratee(value, key, object)] = value; + baseAssignValue(result, iteratee(value, key, object), value); }); return result; } @@ -13045,7 +13215,7 @@ iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[key] = iteratee(value, key, object); + baseAssignValue(result, key, iteratee(value, key, object)); }); return result; } @@ -13089,7 +13259,7 @@ * This method is like `_.merge` except that it accepts `customizer` which * is invoked to produce the merged values of the destination and source * properties. If `customizer` returns `undefined`, merging is handled by the - * method instead. The `customizer` is invoked with seven arguments: + * method instead. The `customizer` is invoked with six arguments: * (objValue, srcValue, key, object, source, stack). * * **Note:** This method mutates `object`. @@ -13139,11 +13309,11 @@ * _.omit(object, ['a', 'c']); * // => { 'b': '2' } */ - var omit = baseRest(function(object, props) { + var omit = flatRest(function(object, props) { if (object == null) { return {}; } - props = arrayMap(baseFlatten(props, 1), toKey); + props = arrayMap(props, toKey); return basePick(object, baseDifference(getAllKeysIn(object), props)); }); @@ -13188,8 +13358,8 @@ * _.pick(object, ['a', 'c']); * // => { 'a': 1, 'c': 3 } */ - var pick = baseRest(function(object, props) { - return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey)); + var pick = flatRest(function(object, props) { + return object == null ? {} : basePick(object, arrayMap(props, toKey)); }); /** @@ -13843,8 +14013,8 @@ } /** - * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to - * their corresponding HTML entities. + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional * characters use a third-party library like [_he_](https://mths.be/he). @@ -13855,12 +14025,6 @@ * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * - * Backticks are escaped because in IE < 9, they can break out of - * attribute values or HTML comments. See [#59](https://html5sec.org/#59), - * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and - * [#133](https://html5sec.org/#133) of the - * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. - * * When working with HTML you should always * [quote attribute values](http://wonko.com/post/html-escaping) to reduce * XSS vectors. @@ -14103,15 +14267,12 @@ * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - // Chrome fails to trim leading whitespace characters. - // See https://bugs.chromium.org/p/v8/issues/detail?id=3109 for more details. if (guard || radix == null) { radix = 0; } else if (radix) { radix = +radix; } - string = toString(string).replace(reTrim, ''); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + return nativeParseInt(toString(string), radix || 0); } /** @@ -14350,7 +14511,8 @@ * compiled({ 'user': 'barney' }); * // => 'hello barney!' * - * // Use the ES delimiter as an alternative to the default "interpolate" delimiter. + * // Use the ES template literal delimiter as an "interpolate" delimiter. + * // Disable support by replacing the "interpolate" delimiter. * var compiled = _.template('hello ${ user }!'); * compiled({ 'user': 'pebbles' }); * // => 'hello pebbles!' @@ -14751,7 +14913,7 @@ /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to + * `&`, `<`, `>`, `"`, and `'` in `string` to * their corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional @@ -14905,10 +15067,10 @@ * jQuery(element).on('click', view.click); * // => Logs 'clicked docs' when clicked. */ - var bindAll = baseRest(function(object, methodNames) { - arrayEach(baseFlatten(methodNames, 1), function(key) { + var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { key = toKey(key); - object[key] = bind(object[key], object); + baseAssignValue(object, key, bind(object[key], object)); }); return object; }); diff --git a/mapKeys.js b/mapKeys.js index 5eade74ac..8c59fd09b 100644 --- a/mapKeys.js +++ b/mapKeys.js @@ -1,4 +1,4 @@ -define(['./_baseForOwn', './_baseIteratee'], function(baseForOwn, baseIteratee) { +define(['./_baseAssignValue', './_baseForOwn', './_baseIteratee'], function(baseAssignValue, baseForOwn, baseIteratee) { /** * The opposite of `_.mapValues`; this method creates an object with the @@ -26,7 +26,7 @@ define(['./_baseForOwn', './_baseIteratee'], function(baseForOwn, baseIteratee) iteratee = baseIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[iteratee(value, key, object)] = value; + baseAssignValue(result, iteratee(value, key, object), value); }); return result; } diff --git a/mapValues.js b/mapValues.js index 997eec8c9..780e8d8cb 100644 --- a/mapValues.js +++ b/mapValues.js @@ -1,4 +1,4 @@ -define(['./_baseForOwn', './_baseIteratee'], function(baseForOwn, baseIteratee) { +define(['./_baseAssignValue', './_baseForOwn', './_baseIteratee'], function(baseAssignValue, baseForOwn, baseIteratee) { /** * Creates an object with the same keys as `object` and values generated @@ -33,7 +33,7 @@ define(['./_baseForOwn', './_baseIteratee'], function(baseForOwn, baseIteratee) iteratee = baseIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { - result[key] = iteratee(value, key, object); + baseAssignValue(result, key, iteratee(value, key, object)); }); return result; } diff --git a/memoize.js b/memoize.js index 662b748f8..81406ddae 100644 --- a/memoize.js +++ b/memoize.js @@ -60,14 +60,14 @@ define(['./_MapCache'], function(MapCache) { return cache.get(key); } var result = func.apply(this, args); - memoized.cache = cache.set(key, result); + memoized.cache = cache.set(key, result) || cache; return result; }; memoized.cache = new (memoize.Cache || MapCache); return memoized; } - // Assign cache to `_.memoize`. + // Expose `MapCache`. memoize.Cache = MapCache; return memoize; diff --git a/mergeWith.js b/mergeWith.js index b4da681f9..50216d5d3 100644 --- a/mergeWith.js +++ b/mergeWith.js @@ -4,7 +4,7 @@ define(['./_baseMerge', './_createAssigner'], function(baseMerge, createAssigner * This method is like `_.merge` except that it accepts `customizer` which * is invoked to produce the merged values of the destination and source * properties. If `customizer` returns `undefined`, merging is handled by the - * method instead. The `customizer` is invoked with seven arguments: + * method instead. The `customizer` is invoked with six arguments: * (objValue, srcValue, key, object, source, stack). * * **Note:** This method mutates `object`. diff --git a/omit.js b/omit.js index fdebc8704..d4ec42520 100644 --- a/omit.js +++ b/omit.js @@ -1,4 +1,4 @@ -define(['./_arrayMap', './_baseDifference', './_baseFlatten', './_basePick', './_baseRest', './_getAllKeysIn', './_toKey'], function(arrayMap, baseDifference, baseFlatten, basePick, baseRest, getAllKeysIn, toKey) { +define(['./_arrayMap', './_baseDifference', './_basePick', './_flatRest', './_getAllKeysIn', './_toKey'], function(arrayMap, baseDifference, basePick, flatRest, getAllKeysIn, toKey) { /** * The opposite of `_.pick`; this method creates an object composed of the @@ -19,11 +19,11 @@ define(['./_arrayMap', './_baseDifference', './_baseFlatten', './_basePick', './ * _.omit(object, ['a', 'c']); * // => { 'b': '2' } */ - var omit = baseRest(function(object, props) { + var omit = flatRest(function(object, props) { if (object == null) { return {}; } - props = arrayMap(baseFlatten(props, 1), toKey); + props = arrayMap(props, toKey); return basePick(object, baseDifference(getAllKeysIn(object), props)); }); diff --git a/overArgs.js b/overArgs.js index 9e8ba0597..9770ceca2 100644 --- a/overArgs.js +++ b/overArgs.js @@ -1,4 +1,4 @@ -define(['./_apply', './_arrayMap', './_baseFlatten', './_baseIteratee', './_baseRest', './_baseUnary', './isArray'], function(apply, arrayMap, baseFlatten, baseIteratee, baseRest, baseUnary, isArray) { +define(['./_apply', './_arrayMap', './_baseFlatten', './_baseIteratee', './_baseRest', './_baseUnary', './_castRest', './isArray'], function(apply, arrayMap, baseFlatten, baseIteratee, baseRest, baseUnary, castRest, isArray) { /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min; @@ -34,7 +34,7 @@ define(['./_apply', './_arrayMap', './_baseFlatten', './_baseIteratee', './_base * func(10, 5); * // => [100, 10] */ - var overArgs = baseRest(function(func, transforms) { + var overArgs = castRest(function(func, transforms) { transforms = (transforms.length == 1 && isArray(transforms[0])) ? arrayMap(transforms[0], baseUnary(baseIteratee)) : arrayMap(baseFlatten(transforms, 1), baseUnary(baseIteratee)); diff --git a/package.json b/package.json index 357b9a8e8..18dbde0c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash-amd", - "version": "4.15.0", + "version": "4.16.0", "description": "Lodash exported as AMD modules.", "keywords": "amd, modules, stdlib, util", "homepage": "https://lodash.com/custom-builds", diff --git a/parseInt.js b/parseInt.js index d6aaa0f21..a014efec8 100644 --- a/parseInt.js +++ b/parseInt.js @@ -1,11 +1,5 @@ define(['./_root', './toString'], function(root, toString) { - /** Used to match leading and trailing whitespace. */ - var reTrim = /^\s+|\s+$/g; - - /** Used to detect hexadecimal string values. */ - var reHasHexPrefix = /^0x/i; - /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeParseInt = root.parseInt; @@ -34,15 +28,12 @@ define(['./_root', './toString'], function(root, toString) { * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - // Chrome fails to trim leading whitespace characters. - // See https://bugs.chromium.org/p/v8/issues/detail?id=3109 for more details. if (guard || radix == null) { radix = 0; } else if (radix) { radix = +radix; } - string = toString(string).replace(reTrim, ''); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + return nativeParseInt(toString(string), radix || 0); } return parseInt; diff --git a/pick.js b/pick.js index 392218c3e..f5961cf7d 100644 --- a/pick.js +++ b/pick.js @@ -1,4 +1,4 @@ -define(['./_arrayMap', './_baseFlatten', './_basePick', './_baseRest', './_toKey'], function(arrayMap, baseFlatten, basePick, baseRest, toKey) { +define(['./_arrayMap', './_basePick', './_flatRest', './_toKey'], function(arrayMap, basePick, flatRest, toKey) { /** * Creates an object composed of the picked `object` properties. @@ -17,8 +17,8 @@ define(['./_arrayMap', './_baseFlatten', './_basePick', './_baseRest', './_toKey * _.pick(object, ['a', 'c']); * // => { 'a': 1, 'c': 3 } */ - var pick = baseRest(function(object, props) { - return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey)); + var pick = flatRest(function(object, props) { + return object == null ? {} : basePick(object, arrayMap(props, toKey)); }); return pick; diff --git a/pullAt.js b/pullAt.js index fde274d31..19444d17d 100644 --- a/pullAt.js +++ b/pullAt.js @@ -1,4 +1,4 @@ -define(['./_arrayMap', './_baseAt', './_baseFlatten', './_basePullAt', './_baseRest', './_compareAscending', './_isIndex'], function(arrayMap, baseAt, baseFlatten, basePullAt, baseRest, compareAscending, isIndex) { +define(['./_arrayMap', './_baseAt', './_basePullAt', './_compareAscending', './_flatRest', './_isIndex'], function(arrayMap, baseAt, basePullAt, compareAscending, flatRest, isIndex) { /** * Removes elements from `array` corresponding to `indexes` and returns an @@ -24,9 +24,7 @@ define(['./_arrayMap', './_baseAt', './_baseFlatten', './_basePullAt', './_baseR * console.log(pulled); * // => ['b', 'd'] */ - var pullAt = baseRest(function(array, indexes) { - indexes = baseFlatten(indexes, 1); - + var pullAt = flatRest(function(array, indexes) { var length = array ? array.length : 0, result = baseAt(array, indexes); diff --git a/rearg.js b/rearg.js index ac39ced34..17636cdd2 100644 --- a/rearg.js +++ b/rearg.js @@ -1,4 +1,4 @@ -define(['./_baseFlatten', './_baseRest', './_createWrap'], function(baseFlatten, baseRest, createWrap) { +define(['./_createWrap', './_flatRest'], function(createWrap, flatRest) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -28,8 +28,8 @@ define(['./_baseFlatten', './_baseRest', './_createWrap'], function(baseFlatten, * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] */ - var rearg = baseRest(function(func, indexes) { - return createWrap(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1)); + var rearg = flatRest(function(func, indexes) { + return createWrap(func, REARG_FLAG, undefined, undefined, undefined, indexes); }); return rearg; diff --git a/sample.js b/sample.js index 44c5b4fc1..3bfe87b9e 100644 --- a/sample.js +++ b/sample.js @@ -1,7 +1,4 @@ -define(['./_baseRandom', './isArrayLike', './values'], function(baseRandom, isArrayLike, values) { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; +define(['./_arraySample', './isArrayLike', './values'], function(arraySample, isArrayLike, values) { /** * Gets a random element from `collection`. @@ -18,10 +15,7 @@ define(['./_baseRandom', './isArrayLike', './values'], function(baseRandom, isAr * // => 2 */ function sample(collection) { - var array = isArrayLike(collection) ? collection : values(collection), - length = array.length; - - return length > 0 ? array[baseRandom(0, length - 1)] : undefined; + return arraySample(isArrayLike(collection) ? collection : values(collection)); } return sample; diff --git a/sampleSize.js b/sampleSize.js index 14426bba0..6e8157db6 100644 --- a/sampleSize.js +++ b/sampleSize.js @@ -1,4 +1,4 @@ -define(['./_baseClamp', './_baseRandom', './_isIterateeCall', './toArray', './toInteger'], function(baseClamp, baseRandom, isIterateeCall, toArray, toInteger) { +define(['./_arraySampleSize', './isArrayLike', './_isIterateeCall', './toInteger', './values'], function(arraySampleSize, isArrayLike, isIterateeCall, toInteger, values) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -24,25 +24,12 @@ define(['./_baseClamp', './_baseRandom', './_isIterateeCall', './toArray', './to * // => [2, 3, 1] */ function sampleSize(collection, n, guard) { - var index = -1, - result = toArray(collection), - length = result.length, - lastIndex = length - 1; - if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { n = 1; } else { - n = baseClamp(toInteger(n), 0, length); + n = toInteger(n); } - while (++index < n) { - var rand = baseRandom(index, lastIndex), - value = result[rand]; - - result[rand] = result[index]; - result[index] = value; - } - result.length = n; - return result; + return arraySampleSize(isArrayLike(collection) ? collection : values(collection), n); } return sampleSize; diff --git a/shuffle.js b/shuffle.js index 852e98f72..5035e189e 100644 --- a/shuffle.js +++ b/shuffle.js @@ -1,7 +1,4 @@ -define(['./sampleSize'], function(sampleSize) { - - /** Used as references for the maximum length and index of an array. */ - var MAX_ARRAY_LENGTH = 4294967295; +define(['./_copyArray', './isArrayLike', './_shuffleSelf', './values'], function(copyArray, isArrayLike, shuffleSelf, values) { /** * Creates an array of shuffled values, using a version of the @@ -19,7 +16,10 @@ define(['./sampleSize'], function(sampleSize) { * // => [4, 1, 3, 2] */ function shuffle(collection) { - return sampleSize(collection, MAX_ARRAY_LENGTH); + return shuffleSelf(isArrayLike(collection) + ? copyArray(collection) + : values(collection) + ); } return shuffle; diff --git a/sortBy.js b/sortBy.js index 8592da28b..18f167cf5 100644 --- a/sortBy.js +++ b/sortBy.js @@ -23,16 +23,11 @@ define(['./_baseFlatten', './_baseOrderBy', './_baseRest', './_isIterateeCall'], * { 'user': 'barney', 'age': 34 } * ]; * - * _.sortBy(users, function(o) { return o.user; }); + * _.sortBy(users, [function(o) { return o.user; }]); * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] * * _.sortBy(users, ['user', 'age']); * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] - * - * _.sortBy(users, 'user', function(o) { - * return Math.floor(o.age / 10); - * }); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] */ var sortBy = baseRest(function(collection, iteratees) { if (collection == null) { diff --git a/template.js b/template.js index 3325a89fc..5657c599c 100644 --- a/template.js +++ b/template.js @@ -79,7 +79,8 @@ define(['./_assignInDefaults', './assignInWith', './attempt', './_baseValues', ' * compiled({ 'user': 'barney' }); * // => 'hello barney!' * - * // Use the ES delimiter as an alternative to the default "interpolate" delimiter. + * // Use the ES template literal delimiter as an "interpolate" delimiter. + * // Disable support by replacing the "interpolate" delimiter. * var compiled = _.template('hello ${ user }!'); * compiled({ 'user': 'pebbles' }); * // => 'hello pebbles!' diff --git a/unescape.js b/unescape.js index e3b9ce9e5..4005f49ae 100644 --- a/unescape.js +++ b/unescape.js @@ -6,7 +6,7 @@ define(['./toString', './_unescapeHtmlChar'], function(toString, unescapeHtmlCha /** * The inverse of `_.escape`; this method converts the HTML entities - * `&`, `<`, `>`, `"`, `'`, and ``` in `string` to + * `&`, `<`, `>`, `"`, and `'` in `string` to * their corresponding characters. * * **Note:** No other HTML entities are unescaped. To unescape additional diff --git a/uniq.js b/uniq.js index 927a24933..63978dda3 100644 --- a/uniq.js +++ b/uniq.js @@ -3,8 +3,9 @@ define(['./_baseUniq'], function(baseUniq) { /** * Creates a duplicate-free version of an array, using * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons, in which only the first occurrence of each - * element is kept. + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. * * @static * @memberOf _ diff --git a/uniqBy.js b/uniqBy.js index dbd4d5f31..db4d9d03e 100644 --- a/uniqBy.js +++ b/uniqBy.js @@ -3,7 +3,9 @@ define(['./_baseIteratee', './_baseUniq'], function(baseIteratee, baseUniq) { /** * This method is like `_.uniq` except that it accepts `iteratee` which is * invoked for each element in `array` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). * * @static * @memberOf _ diff --git a/uniqWith.js b/uniqWith.js index 8d510cb0b..ae65156b9 100644 --- a/uniqWith.js +++ b/uniqWith.js @@ -5,8 +5,9 @@ define(['./_baseUniq'], function(baseUniq) { /** * This method is like `_.uniq` except that it accepts `comparator` which - * is invoked to compare elements of `array`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _ diff --git a/wrapperAt.js b/wrapperAt.js index a28296e5c..907181c02 100644 --- a/wrapperAt.js +++ b/wrapperAt.js @@ -1,4 +1,4 @@ -define(['./_LazyWrapper', './_LodashWrapper', './_baseAt', './_baseFlatten', './_baseRest', './_isIndex', './thru'], function(LazyWrapper, LodashWrapper, baseAt, baseFlatten, baseRest, isIndex, thru) { +define(['./_LazyWrapper', './_LodashWrapper', './_baseAt', './_flatRest', './_isIndex', './thru'], function(LazyWrapper, LodashWrapper, baseAt, flatRest, isIndex, thru) { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; @@ -19,8 +19,7 @@ define(['./_LazyWrapper', './_LodashWrapper', './_baseAt', './_baseFlatten', './ * _(object).at(['a[0].b.c', 'a[1]']).value(); * // => [3, 4] */ - var wrapperAt = baseRest(function(paths) { - paths = baseFlatten(paths, 1); + var wrapperAt = flatRest(function(paths) { var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, diff --git a/xorBy.js b/xorBy.js index b34ee9c44..b78ca30ee 100644 --- a/xorBy.js +++ b/xorBy.js @@ -6,8 +6,9 @@ define(['./_arrayFilter', './_baseIteratee', './_baseRest', './_baseXor', './isA /** * This method is like `_.xor` except that it accepts `iteratee` which is * invoked for each element of each `arrays` to generate the criterion by - * which by which they're compared. The iteratee is invoked with one argument: - * (value). + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). * * @static * @memberOf _ diff --git a/xorWith.js b/xorWith.js index eb2519449..775a9ccee 100644 --- a/xorWith.js +++ b/xorWith.js @@ -5,8 +5,9 @@ define(['./_arrayFilter', './_baseRest', './_baseXor', './isArrayLikeObject', '. /** * This method is like `_.xor` except that it accepts `comparator` which is - * invoked to compare elements of `arrays`. The comparator is invoked with - * two arguments: (arrVal, othVal). + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). * * @static * @memberOf _