From 94ac73824fc0a19d776bc8de47903f34e136cb75 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 17 Sep 2016 22:28:43 -0700 Subject: [PATCH] Bump to v4.16.0. --- README.md | 6 +++--- _Stack.js | 3 ++- _arraySample.js | 16 ++++++++++++++++ _arraySampleSize.js | 18 ++++++++++++++++++ _arrayShuffle.js | 15 +++++++++++++++ _assignMergeValue.js | 3 ++- _assignValue.js | 3 ++- _baseAssignValue.js | 26 ++++++++++++++++++++++++++ _baseClone.js | 4 ---- _baseIndexOf.js | 16 ++++------------ _baseIsEqualDeep.js | 5 ++--- _baseIsNative.js | 3 +-- _basePickBy.js | 4 +++- _baseRest.js | 26 ++++---------------------- _baseSetData.js | 2 +- _baseSetToString.js | 22 ++++++++++++++++++++++ _cacheHas.js | 2 +- _castRest.js | 14 ++++++++++++++ _copyObject.js | 11 ++++++++++- _countHolders.js | 2 +- _createFlow.js | 7 ++----- _createOver.js | 10 +++------- _deburrLetter.js | 2 +- _defineProperty.js | 11 ----------- _equalArrays.js | 5 +++-- _escapeHtmlChar.js | 3 +-- _flatRest.js | 16 ++++++++++++++++ _getTag.js | 3 +-- _hasPath.js | 10 +++++----- _hashClear.js | 1 + _hashDelete.js | 4 +++- _hashSet.js | 1 + _insertWrapDetails.js | 8 +++++--- _isHostObject.js | 20 -------------------- _listCacheClear.js | 1 + _listCacheDelete.js | 1 + _listCacheSet.js | 1 + _mapCacheClear.js | 1 + _mapCacheDelete.js | 4 +++- _mapCacheSet.js | 6 +++++- _memoizeCapped.js | 26 ++++++++++++++++++++++++++ _nativeDefineProperty.js | 6 ++++++ _overRest.js | 36 ++++++++++++++++++++++++++++++++++++ _setData.js | 26 ++------------------------ _setToString.js | 14 ++++++++++++++ _setWrapToString.js | 14 ++++---------- _shortOut.js | 37 +++++++++++++++++++++++++++++++++++++ _shuffleSelf.js | 25 +++++++++++++++++++++++++ _stackClear.js | 1 + _stackDelete.js | 6 +++++- _stackSet.js | 12 +++++++----- _strictIndexOf.js | 23 +++++++++++++++++++++++ _strictLastIndexOf.js | 21 +++++++++++++++++++++ _stringToPath.js | 4 ++-- _unescapeHtmlChar.js | 3 +-- _unicodeSize.js | 2 +- assign.js | 8 +------- at.js | 7 ++----- bindAll.js | 10 +++++----- concat.js | 11 ++++++----- countBy.js | 7 ++++++- defer.js | 2 +- difference.js | 4 ++-- differenceBy.js | 5 +++-- differenceWith.js | 6 +++--- escape.js | 10 ++-------- forEach.js | 2 +- groupBy.js | 3 ++- intersection.js | 4 ++-- intersectionBy.js | 5 +++-- intersectionWith.js | 6 +++--- isElement.js | 2 +- isEmpty.js | 8 +------- isObject.js | 2 +- isObjectLike.js | 2 +- isPlainObject.js | 4 +--- keyBy.js | 3 ++- lastIndexOf.js | 19 +++++-------------- lodash.default.js | 2 +- mapKeys.js | 3 ++- mapValues.js | 3 ++- memoize.js | 4 ++-- mergeWith.js | 2 +- omit.js | 7 +++---- overArgs.js | 3 ++- package.json | 3 ++- parseInt.js | 11 +---------- pick.js | 7 +++---- pullAt.js | 7 ++----- rearg.js | 7 +++---- sample.js | 7 ++----- sampleSize.js | 23 +++++------------------ shuffle.js | 13 ++++++++----- sortBy.js | 7 +------ template.js | 3 ++- unescape.js | 2 +- uniq.js | 5 +++-- uniqBy.js | 4 +++- uniqWith.js | 5 +++-- wrapperAt.js | 6 ++---- xorBy.js | 5 +++-- xorWith.js | 5 +++-- 102 files changed, 526 insertions(+), 320 deletions(-) create mode 100644 _arraySample.js create mode 100644 _arraySampleSize.js create mode 100644 _arrayShuffle.js create mode 100644 _baseAssignValue.js create mode 100644 _baseSetToString.js create mode 100644 _castRest.js delete mode 100644 _defineProperty.js create mode 100644 _flatRest.js delete mode 100644 _isHostObject.js create mode 100644 _memoizeCapped.js create mode 100644 _nativeDefineProperty.js create mode 100644 _overRest.js create mode 100644 _setToString.js create mode 100644 _shortOut.js create mode 100644 _shuffleSelf.js create mode 100644 _strictIndexOf.js create mode 100644 _strictLastIndexOf.js diff --git a/README.md b/README.md index 3048b8324..a4062cc6a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# lodash-es v4.15.0 +# lodash-es v4.16.0 The [Lodash](https://lodash.com/) library exported as [ES](http://www.ecma-international.org/ecma-262/6.0/) modules. Generated using [lodash-cli](https://www.npmjs.com/package/lodash-cli): -```bash +```shell $ lodash modularize exports=es -o ./ ``` -See the [package source](https://github.com/lodash/lodash/tree/4.15.0-es) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.16.0-es) for more details. diff --git a/_Stack.js b/_Stack.js index c9bc171d2..77c3cf311 100644 --- a/_Stack.js +++ b/_Stack.js @@ -13,7 +13,8 @@ import stackSet from './_stackSet.js'; * @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..2b555967d --- /dev/null +++ b/_arraySample.js @@ -0,0 +1,16 @@ +import baseRandom from './_baseRandom.js'; + +/** + * 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; +} + +export default arraySample; diff --git a/_arraySampleSize.js b/_arraySampleSize.js new file mode 100644 index 000000000..9fede136e --- /dev/null +++ b/_arraySampleSize.js @@ -0,0 +1,18 @@ +import arrayShuffle from './_arrayShuffle.js'; +import baseClamp from './_baseClamp.js'; + +/** + * 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; +} + +export default arraySampleSize; diff --git a/_arrayShuffle.js b/_arrayShuffle.js new file mode 100644 index 000000000..493e65b57 --- /dev/null +++ b/_arrayShuffle.js @@ -0,0 +1,15 @@ +import copyArray from './_copyArray.js'; +import shuffleSelf from './_shuffleSelf.js'; + +/** + * 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)); +} + +export default arrayShuffle; diff --git a/_assignMergeValue.js b/_assignMergeValue.js index cb4c2473a..aa3992167 100644 --- a/_assignMergeValue.js +++ b/_assignMergeValue.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import eq from './eq.js'; /** @@ -12,7 +13,7 @@ import eq from './eq.js'; 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 9c2110b37..c858e92e0 100644 --- a/_assignValue.js +++ b/_assignValue.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import eq from './eq.js'; /** Used for built-in method references. */ @@ -20,7 +21,7 @@ function assignValue(object, key, value) { 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..540a61366 --- /dev/null +++ b/_baseAssignValue.js @@ -0,0 +1,26 @@ +/** 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; + } +} + +export default baseAssignValue; diff --git a/_baseClone.js b/_baseClone.js index bd734712c..b2e134688 100644 --- a/_baseClone.js +++ b/_baseClone.js @@ -12,7 +12,6 @@ import initCloneByTag from './_initCloneByTag.js'; import initCloneObject from './_initCloneObject.js'; import isArray from './isArray.js'; import isBuffer from './isBuffer.js'; -import isHostObject from './_isHostObject.js'; import isObject from './isObject.js'; import keys from './keys.js'; @@ -100,9 +99,6 @@ function baseClone(value, isDeep, isFull, customizer, key, object, stack) { 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 69a5c3b21..027e11dfd 100644 --- a/_baseIndexOf.js +++ b/_baseIndexOf.js @@ -1,5 +1,6 @@ import baseFindIndex from './_baseFindIndex.js'; import baseIsNaN from './_baseIsNaN.js'; +import strictIndexOf from './_strictIndexOf.js'; /** * The base implementation of `_.indexOf` without `fromIndex` bounds checks. @@ -11,18 +12,9 @@ import baseIsNaN from './_baseIsNaN.js'; * @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); } export default baseIndexOf; diff --git a/_baseIsEqualDeep.js b/_baseIsEqualDeep.js index bd5d0ef62..f0bfa37b7 100644 --- a/_baseIsEqualDeep.js +++ b/_baseIsEqualDeep.js @@ -4,7 +4,6 @@ import equalByTag from './_equalByTag.js'; import equalObjects from './_equalObjects.js'; import getTag from './_getTag.js'; import isArray from './isArray.js'; -import isHostObject from './_isHostObject.js'; import isTypedArray from './isTypedArray.js'; /** Used to compose bitmasks for comparison styles. */ @@ -50,8 +49,8 @@ function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { 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 8e38ee54b..04c185431 100644 --- a/_baseIsNative.js +++ b/_baseIsNative.js @@ -1,5 +1,4 @@ import isFunction from './isFunction.js'; -import isHostObject from './_isHostObject.js'; import isMasked from './_isMasked.js'; import isObject from './isObject.js'; import toSource from './_toSource.js'; @@ -41,7 +40,7 @@ function baseIsNative(value) { 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 5352a3b7e..bf027dd22 100644 --- a/_basePickBy.js +++ b/_basePickBy.js @@ -1,3 +1,5 @@ +import baseAssignValue from './_baseAssignValue.js'; + /** * The base implementation of `_.pickBy` without support for iteratee shorthands. * @@ -17,7 +19,7 @@ function basePickBy(object, props, predicate) { 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 6ca3256c6..a31537100 100644 --- a/_baseRest.js +++ b/_baseRest.js @@ -1,7 +1,6 @@ -import apply from './_apply.js'; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; +import identity from './identity.js'; +import overRest from './_overRest.js'; +import setToString from './_setToString.js'; /** * The base implementation of `_.rest` which doesn't validate or coerce arguments. @@ -12,24 +11,7 @@ var nativeMax = Math.max; * @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 + ''); } export default baseRest; diff --git a/_baseSetData.js b/_baseSetData.js index 0ffc99b45..8d57b0b39 100644 --- a/_baseSetData.js +++ b/_baseSetData.js @@ -2,7 +2,7 @@ import identity from './identity.js'; import metaMap from './_metaMap.js'; /** - * 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..1a80d1570 --- /dev/null +++ b/_baseSetToString.js @@ -0,0 +1,22 @@ +import constant from './constant.js'; +import identity from './identity.js'; +import nativeDefineProperty from './_nativeDefineProperty.js'; + +/** + * 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 + }); +}; + +export default baseSetToString; diff --git a/_cacheHas.js b/_cacheHas.js index b0110d076..374a88654 100644 --- a/_cacheHas.js +++ b/_cacheHas.js @@ -1,5 +1,5 @@ /** - * 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..6f43d021a --- /dev/null +++ b/_castRest.js @@ -0,0 +1,14 @@ +import baseRest from './_baseRest.js'; + +/** + * 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; + +export default castRest; diff --git a/_copyObject.js b/_copyObject.js index 7bd5f77b0..4e2475553 100644 --- a/_copyObject.js +++ b/_copyObject.js @@ -1,4 +1,5 @@ import assignValue from './_assignValue.js'; +import baseAssignValue from './_baseAssignValue.js'; /** * Copies properties of `source` to `object`. @@ -11,6 +12,7 @@ import assignValue from './_assignValue.js'; * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { + var isNew = !object; object || (object = {}); var index = -1, @@ -23,7 +25,14 @@ function copyObject(source, props, object, customizer) { ? 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 c4b76fb7b..0767946dd 100644 --- a/_countHolders.js +++ b/_countHolders.js @@ -12,7 +12,7 @@ function countHolders(array, placeholder) { while (length--) { if (array[length] === placeholder) { - result++; + ++result; } } return result; diff --git a/_createFlow.js b/_createFlow.js index c2e5e2fe7..443c53adb 100644 --- a/_createFlow.js +++ b/_createFlow.js @@ -1,6 +1,5 @@ import LodashWrapper from './_LodashWrapper.js'; -import baseFlatten from './_baseFlatten.js'; -import baseRest from './_baseRest.js'; +import flatRest from './_flatRest.js'; import getData from './_getData.js'; import getFuncName from './_getFuncName.js'; import isArray from './isArray.js'; @@ -26,9 +25,7 @@ var CURRY_FLAG = 8, * @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 2c842bef6..a79f37385 100644 --- a/_createOver.js +++ b/_createOver.js @@ -1,10 +1,9 @@ import apply from './_apply.js'; import arrayMap from './_arrayMap.js'; -import baseFlatten from './_baseFlatten.js'; import baseIteratee from './_baseIteratee.js'; import baseRest from './_baseRest.js'; import baseUnary from './_baseUnary.js'; -import isArray from './isArray.js'; +import flatRest from './_flatRest.js'; /** * Creates a function like `_.over`. @@ -14,11 +13,8 @@ import isArray from './isArray.js'; * @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 896d14c50..88a7b99df 100644 --- a/_deburrLetter.js +++ b/_deburrLetter.js @@ -55,7 +55,7 @@ var deburredLetters = { '\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 fcab11552..000000000 --- a/_defineProperty.js +++ /dev/null @@ -1,11 +0,0 @@ -import getNative from './_getNative.js'; - -/* Used to set `toString` methods. */ -var defineProperty = (function() { - var func = getNative(Object, 'defineProperty'), - name = getNative.name; - - return (name && name.length > 2) ? func : undefined; -}()); - -export default defineProperty; diff --git a/_equalArrays.js b/_equalArrays.js index 2a2ecfaf7..a19c673e8 100644 --- a/_equalArrays.js +++ b/_equalArrays.js @@ -1,5 +1,6 @@ import SetCache from './_SetCache.js'; import arraySome from './_arraySome.js'; +import cacheHas from './_cacheHas.js'; /** Used to compose bitmasks for comparison styles. */ var UNORDERED_COMPARE_FLAG = 1, @@ -59,9 +60,9 @@ function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { // 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 6535d1a12..536240335 100644 --- a/_escapeHtmlChar.js +++ b/_escapeHtmlChar.js @@ -6,8 +6,7 @@ var htmlEscapes = { '<': '<', '>': '>', '"': '"', - "'": ''', - '`': '`' + "'": ''' }; /** diff --git a/_flatRest.js b/_flatRest.js new file mode 100644 index 000000000..45dc4390b --- /dev/null +++ b/_flatRest.js @@ -0,0 +1,16 @@ +import flatten from './flatten.js'; +import overRest from './_overRest.js'; +import setToString from './_setToString.js'; + +/** + * 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 + ''); +} + +export default flatRest; diff --git a/_getTag.js b/_getTag.js index d2c415613..2b921e200 100644 --- a/_getTag.js +++ b/_getTag.js @@ -41,8 +41,7 @@ var dataViewCtorString = toSource(DataView), */ 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 019cf4135..866605ed4 100644 --- a/_hasPath.js +++ b/_hasPath.js @@ -18,9 +18,9 @@ import toKey from './_toKey.js'; 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]); @@ -29,10 +29,10 @@ function hasPath(object, path, hasFunc) { } 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 e7f7ab5ef..5b7cc2d08 100644 --- a/_hashClear.js +++ b/_hashClear.js @@ -9,6 +9,7 @@ import nativeCreate from './_nativeCreate.js'; */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; } export default hashClear; diff --git a/_hashDelete.js b/_hashDelete.js index 857dbd3e0..509839f51 100644 --- a/_hashDelete.js +++ b/_hashDelete.js @@ -9,7 +9,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; } export default hashDelete; diff --git a/_hashSet.js b/_hashSet.js index 13af365f6..63a0115b0 100644 --- a/_hashSet.js +++ b/_hashSet.js @@ -15,6 +15,7 @@ var HASH_UNDEFINED = '__lodash_hash_undefined__'; */ 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 3ac974c00..5191b7aba 100644 --- a/_insertWrapDetails.js +++ b/_insertWrapDetails.js @@ -10,9 +10,11 @@ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/; * @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 29382d12f..000000000 --- a/_isHostObject.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * 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; -} - -export default isHostObject; diff --git a/_listCacheClear.js b/_listCacheClear.js index 493e847d2..8cfa1843c 100644 --- a/_listCacheClear.js +++ b/_listCacheClear.js @@ -7,6 +7,7 @@ */ function listCacheClear() { this.__data__ = []; + this.size = 0; } export default listCacheClear; diff --git a/_listCacheDelete.js b/_listCacheDelete.js index 72b3453c3..b08c834a7 100644 --- a/_listCacheDelete.js +++ b/_listCacheDelete.js @@ -28,6 +28,7 @@ function listCacheDelete(key) { } else { splice.call(data, index, 1); } + --this.size; return true; } diff --git a/_listCacheSet.js b/_listCacheSet.js index 5777e0557..8c5a1980e 100644 --- a/_listCacheSet.js +++ b/_listCacheSet.js @@ -15,6 +15,7 @@ function listCacheSet(key, value) { 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 1a8dc6cb3..e6b3d9c26 100644 --- a/_mapCacheClear.js +++ b/_mapCacheClear.js @@ -10,6 +10,7 @@ import Map from './_Map.js'; * @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 e8614a598..1afc18fe2 100644 --- a/_mapCacheDelete.js +++ b/_mapCacheDelete.js @@ -10,7 +10,9 @@ import getMapData from './_getMapData.js'; * @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; } export default mapCacheDelete; diff --git a/_mapCacheSet.js b/_mapCacheSet.js index b10aeda33..e757c360e 100644 --- a/_mapCacheSet.js +++ b/_mapCacheSet.js @@ -11,7 +11,11 @@ import getMapData from './_getMapData.js'; * @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..d2b93994d --- /dev/null +++ b/_memoizeCapped.js @@ -0,0 +1,26 @@ +import memoize from './memoize.js'; + +/** 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; +} + +export default memoizeCapped; diff --git a/_nativeDefineProperty.js b/_nativeDefineProperty.js new file mode 100644 index 000000000..3af0910a2 --- /dev/null +++ b/_nativeDefineProperty.js @@ -0,0 +1,6 @@ +import getNative from './_getNative.js'; + +/* Built-in method references that are verified to be native. */ +var nativeDefineProperty = getNative(Object, 'defineProperty'); + +export default nativeDefineProperty; diff --git a/_overRest.js b/_overRest.js new file mode 100644 index 000000000..f4f79cb6e --- /dev/null +++ b/_overRest.js @@ -0,0 +1,36 @@ +import apply from './_apply.js'; + +/* 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); + }; +} + +export default overRest; diff --git a/_setData.js b/_setData.js index 38cae5be8..8b6bac9a7 100644 --- a/_setData.js +++ b/_setData.js @@ -1,9 +1,5 @@ import baseSetData from './_baseSetData.js'; -import now from './now.js'; - -/** Used to detect hot functions by number of calls within a span of milliseconds. */ -var HOT_COUNT = 150, - HOT_SPAN = 16; +import shortOut from './_shortOut.js'; /** * Sets metadata for `func`. @@ -19,24 +15,6 @@ var HOT_COUNT = 150, * @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); export default setData; diff --git a/_setToString.js b/_setToString.js new file mode 100644 index 000000000..db2dd26cb --- /dev/null +++ b/_setToString.js @@ -0,0 +1,14 @@ +import baseSetToString from './_baseSetToString.js'; +import shortOut from './_shortOut.js'; + +/** + * 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); + +export default setToString; diff --git a/_setWrapToString.js b/_setWrapToString.js index 85f44b3f8..16b08fdd4 100644 --- a/_setWrapToString.js +++ b/_setWrapToString.js @@ -1,8 +1,6 @@ -import constant from './constant.js'; -import defineProperty from './_defineProperty.js'; import getWrapDetails from './_getWrapDetails.js'; -import identity from './identity.js'; import insertWrapDetails from './_insertWrapDetails.js'; +import setToString from './_setToString.js'; import updateWrapDetails from './_updateWrapDetails.js'; /** @@ -15,13 +13,9 @@ import updateWrapDetails from './_updateWrapDetails.js'; * @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))); +} export default setWrapToString; diff --git a/_shortOut.js b/_shortOut.js new file mode 100644 index 000000000..e792abb00 --- /dev/null +++ b/_shortOut.js @@ -0,0 +1,37 @@ +/** 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); + }; +} + +export default shortOut; diff --git a/_shuffleSelf.js b/_shuffleSelf.js new file mode 100644 index 000000000..7eadd0e82 --- /dev/null +++ b/_shuffleSelf.js @@ -0,0 +1,25 @@ +import baseRandom from './_baseRandom.js'; + +/** + * 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; +} + +export default shuffleSelf; diff --git a/_stackClear.js b/_stackClear.js index 763cb12b2..d4b10b0d3 100644 --- a/_stackClear.js +++ b/_stackClear.js @@ -9,6 +9,7 @@ import ListCache from './_ListCache.js'; */ function stackClear() { this.__data__ = new ListCache; + this.size = 0; } export default stackClear; diff --git a/_stackDelete.js b/_stackDelete.js index 429ab21fd..c3df897c0 100644 --- a/_stackDelete.js +++ b/_stackDelete.js @@ -8,7 +8,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; } export default stackDelete; diff --git a/_stackSet.js b/_stackSet.js index 000735cd3..a85af6cfe 100644 --- a/_stackSet.js +++ b/_stackSet.js @@ -16,16 +16,18 @@ var LARGE_ARRAY_SIZE = 200; * @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..0dfad1ec9 --- /dev/null +++ b/_strictIndexOf.js @@ -0,0 +1,23 @@ +/** + * 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; +} + +export default strictIndexOf; diff --git a/_strictLastIndexOf.js b/_strictLastIndexOf.js new file mode 100644 index 000000000..6ddf04ccf --- /dev/null +++ b/_strictLastIndexOf.js @@ -0,0 +1,21 @@ +/** + * 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; +} + +export default strictLastIndexOf; diff --git a/_stringToPath.js b/_stringToPath.js index 0df430cff..1a61952ec 100644 --- a/_stringToPath.js +++ b/_stringToPath.js @@ -1,4 +1,4 @@ -import memoize from './memoize.js'; +import memoizeCapped from './_memoizeCapped.js'; import toString from './toString.js'; /** Used to match property names within property paths. */ @@ -15,7 +15,7 @@ var reEscapeChar = /\\(\\)?/g; * @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 d3dbcecb2..e1876cc04 100644 --- a/_unescapeHtmlChar.js +++ b/_unescapeHtmlChar.js @@ -6,8 +6,7 @@ var htmlUnescapes = { '<': '<', '>': '>', '"': '"', - ''': "'", - '`': '`' + ''': "'" }; /** diff --git a/_unicodeSize.js b/_unicodeSize.js index 83117b0db..171d393bb 100644 --- a/_unicodeSize.js +++ b/_unicodeSize.js @@ -34,7 +34,7 @@ var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); 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 fe485002b..ed9329f06 100644 --- a/assign.js +++ b/assign.js @@ -11,12 +11,6 @@ var objectProto = Object.prototype; /** 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. @@ -50,7 +44,7 @@ var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); * // => { '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 92c317338..2a9220a06 100644 --- a/at.js +++ b/at.js @@ -1,6 +1,5 @@ import baseAt from './_baseAt.js'; -import baseFlatten from './_baseFlatten.js'; -import baseRest from './_baseRest.js'; +import flatRest from './_flatRest.js'; /** * Creates an array of values corresponding to `paths` of `object`. @@ -19,8 +18,6 @@ import baseRest from './_baseRest.js'; * _.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); export default at; diff --git a/bindAll.js b/bindAll.js index 05864a24f..37ae093a6 100644 --- a/bindAll.js +++ b/bindAll.js @@ -1,7 +1,7 @@ import arrayEach from './_arrayEach.js'; -import baseFlatten from './_baseFlatten.js'; -import baseRest from './_baseRest.js'; +import baseAssignValue from './_baseAssignValue.js'; import bind from './bind.js'; +import flatRest from './_flatRest.js'; import toKey from './_toKey.js'; /** @@ -30,10 +30,10 @@ import toKey from './_toKey.js'; * 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 1774be94c..4f598c34d 100644 --- a/concat.js +++ b/concat.js @@ -26,17 +26,18 @@ import isArray from './isArray.js'; * // => [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)); } export default concat; diff --git a/countBy.js b/countBy.js index 3d3ea1546..a770f46bf 100644 --- a/countBy.js +++ b/countBy.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import createAggregator from './_createAggregator.js'; /** Used for built-in method references. */ @@ -30,7 +31,11 @@ var hasOwnProperty = objectProto.hasOwnProperty; * // => { '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); + } }); export default countBy; diff --git a/defer.js b/defer.js index 45ae53ffe..7c4c28416 100644 --- a/defer.js +++ b/defer.js @@ -17,7 +17,7 @@ import baseRest from './_baseRest.js'; * _.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 ee6f80ee1..ddc1db57d 100644 --- a/difference.js +++ b/difference.js @@ -6,8 +6,8 @@ import isArrayLikeObject from './isArrayLikeObject.js'; /** * 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 30149e56c..983cc54fa 100644 --- a/differenceBy.js +++ b/differenceBy.js @@ -8,8 +8,9 @@ import last from './last.js'; /** * 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 ab5014e13..980a68cfc 100644 --- a/differenceWith.js +++ b/differenceWith.js @@ -6,9 +6,9 @@ import last from './last.js'; /** * 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 e5ada6da3..adaf72b57 100644 --- a/escape.js +++ b/escape.js @@ -6,8 +6,8 @@ var reUnescapedHtml = /[&<>"'`]/g, 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). @@ -18,12 +18,6 @@ var reUnescapedHtml = /[&<>"'`]/g, * [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 a101d7c33..c0aa120df 100644 --- a/forEach.js +++ b/forEach.js @@ -23,7 +23,7 @@ import isArray from './isArray.js'; * @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 4b55760ee..610aeaddf 100644 --- a/groupBy.js +++ b/groupBy.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import createAggregator from './_createAggregator.js'; /** Used for built-in method references. */ @@ -34,7 +35,7 @@ var groupBy = createAggregator(function(result, value, key) { 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 550f29418..9d4ef19ec 100644 --- a/intersection.js +++ b/intersection.js @@ -6,8 +6,8 @@ import castArrayLikeObject from './_castArrayLikeObject.js'; /** * 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 f4627374a..6886f908a 100644 --- a/intersectionBy.js +++ b/intersectionBy.js @@ -8,8 +8,9 @@ import last from './last.js'; /** * 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 2a7b32c5f..45e93e6a4 100644 --- a/intersectionWith.js +++ b/intersectionWith.js @@ -6,9 +6,9 @@ import last from './last.js'; /** * 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 57d27850c..9ff1ce10a 100644 --- a/isElement.js +++ b/isElement.js @@ -19,7 +19,7 @@ import isPlainObject from './isPlainObject.js'; * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + return value != null && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } export default isElement; diff --git a/isEmpty.js b/isEmpty.js index d9ff00245..48176a256 100644 --- a/isEmpty.js +++ b/isEmpty.js @@ -16,12 +16,6 @@ var objectProto = Object.prototype; /** 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. * @@ -65,7 +59,7 @@ function isEmpty(value) { 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 4f1beaa9d..ddfebd5bb 100644 --- a/isObject.js +++ b/isObject.js @@ -25,7 +25,7 @@ */ function isObject(value) { var type = typeof value; - return !!value && (type == 'object' || type == 'function'); + return value != null && (type == 'object' || type == 'function'); } export default isObject; diff --git a/isObjectLike.js b/isObjectLike.js index 2f56e66ef..0e931b172 100644 --- a/isObjectLike.js +++ b/isObjectLike.js @@ -23,7 +23,7 @@ * // => false */ function isObjectLike(value) { - return !!value && typeof value == 'object'; + return value != null && typeof value == 'object'; } export default isObjectLike; diff --git a/isPlainObject.js b/isPlainObject.js index 0438043e0..a6c81da16 100644 --- a/isPlainObject.js +++ b/isPlainObject.js @@ -1,5 +1,4 @@ import getPrototype from './_getPrototype.js'; -import isHostObject from './_isHostObject.js'; import isObjectLike from './isObjectLike.js'; /** `Object#toString` result references. */ @@ -54,8 +53,7 @@ var objectToString = objectProto.toString; * // => 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 1bf20cffa..561f3f147 100644 --- a/keyBy.js +++ b/keyBy.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import createAggregator from './_createAggregator.js'; /** @@ -30,7 +31,7 @@ import createAggregator from './_createAggregator.js'; * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { - result[key] = value; + baseAssignValue(result, key, value); }); export default keyBy; diff --git a/lastIndexOf.js b/lastIndexOf.js index fb1dcdbd6..edd01a4e9 100644 --- a/lastIndexOf.js +++ b/lastIndexOf.js @@ -1,5 +1,6 @@ import baseFindIndex from './_baseFindIndex.js'; import baseIsNaN from './_baseIsNaN.js'; +import strictLastIndexOf from './_strictLastIndexOf.js'; import toInteger from './toInteger.js'; /* Built-in method references for those with the same name as other `lodash` methods. */ @@ -35,21 +36,11 @@ function lastIndexOf(array, value, fromIndex) { 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); } export default lastIndexOf; diff --git a/lodash.default.js b/lodash.default.js index c3cdf3da7..cf3b259bb 100644 --- a/lodash.default.js +++ b/lodash.default.js @@ -45,7 +45,7 @@ import toInteger from './toInteger.js'; import lodash from './wrapperLodash.js'; /** Used as the semantic version number. */ -var VERSION = '4.15.0'; +var VERSION = '4.16.0'; /** Used to compose bitmasks for function metadata. */ var BIND_KEY_FLAG = 2; diff --git a/mapKeys.js b/mapKeys.js index ac563eb69..24fc6899f 100644 --- a/mapKeys.js +++ b/mapKeys.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import baseForOwn from './_baseForOwn.js'; import baseIteratee from './_baseIteratee.js'; @@ -27,7 +28,7 @@ function mapKeys(object, iteratee) { 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 123930701..bcc48e070 100644 --- a/mapValues.js +++ b/mapValues.js @@ -1,3 +1,4 @@ +import baseAssignValue from './_baseAssignValue.js'; import baseForOwn from './_baseForOwn.js'; import baseIteratee from './_baseIteratee.js'; @@ -34,7 +35,7 @@ function mapValues(object, iteratee) { 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 cd88a4682..271ecd06f 100644 --- a/memoize.js +++ b/memoize.js @@ -60,14 +60,14 @@ function memoize(func, resolver) { 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; export default memoize; diff --git a/mergeWith.js b/mergeWith.js index 1961e6915..6b7e0982d 100644 --- a/mergeWith.js +++ b/mergeWith.js @@ -5,7 +5,7 @@ import createAssigner from './_createAssigner.js'; * 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 2be1b6016..fc8677ab2 100644 --- a/omit.js +++ b/omit.js @@ -1,8 +1,7 @@ import arrayMap from './_arrayMap.js'; import baseDifference from './_baseDifference.js'; -import baseFlatten from './_baseFlatten.js'; import basePick from './_basePick.js'; -import baseRest from './_baseRest.js'; +import flatRest from './_flatRest.js'; import getAllKeysIn from './_getAllKeysIn.js'; import toKey from './_toKey.js'; @@ -25,11 +24,11 @@ import toKey from './_toKey.js'; * _.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 4a47b61d2..c9409f402 100644 --- a/overArgs.js +++ b/overArgs.js @@ -4,6 +4,7 @@ import baseFlatten from './_baseFlatten.js'; import baseIteratee from './_baseIteratee.js'; import baseRest from './_baseRest.js'; import baseUnary from './_baseUnary.js'; +import castRest from './_castRest.js'; import isArray from './isArray.js'; /* Built-in method references for those with the same name as other `lodash` methods. */ @@ -40,7 +41,7 @@ var nativeMin = Math.min; * 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 640f021c4..d3f9f05b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash-es", - "version": "4.15.0", + "version": "4.16.0", "description": "Lodash exported as ES modules.", "keywords": "es6, modules, stdlib, util", "homepage": "https://lodash.com/custom-builds", @@ -9,6 +9,7 @@ "license": "MIT", "jsnext:main": "lodash.js", "main": "lodash.js", + "module": "lodash.js", "author": "John-David Dalton (http://allyoucanleet.com/)", "contributors": [ "John-David Dalton (http://allyoucanleet.com/)", diff --git a/parseInt.js b/parseInt.js index 875da6f14..a5a2dc886 100644 --- a/parseInt.js +++ b/parseInt.js @@ -1,12 +1,6 @@ import root from './_root.js'; import toString from './toString.js'; -/** 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; @@ -35,15 +29,12 @@ var nativeParseInt = root.parseInt; * // => [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); } export default parseInt; diff --git a/pick.js b/pick.js index 1c812a03b..337d5514a 100644 --- a/pick.js +++ b/pick.js @@ -1,7 +1,6 @@ import arrayMap from './_arrayMap.js'; -import baseFlatten from './_baseFlatten.js'; import basePick from './_basePick.js'; -import baseRest from './_baseRest.js'; +import flatRest from './_flatRest.js'; import toKey from './_toKey.js'; /** @@ -21,8 +20,8 @@ import toKey from './_toKey.js'; * _.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)); }); export default pick; diff --git a/pullAt.js b/pullAt.js index 303705bc2..1b84fe25e 100644 --- a/pullAt.js +++ b/pullAt.js @@ -1,9 +1,8 @@ import arrayMap from './_arrayMap.js'; import baseAt from './_baseAt.js'; -import baseFlatten from './_baseFlatten.js'; import basePullAt from './_basePullAt.js'; -import baseRest from './_baseRest.js'; import compareAscending from './_compareAscending.js'; +import flatRest from './_flatRest.js'; import isIndex from './_isIndex.js'; /** @@ -30,9 +29,7 @@ import isIndex from './_isIndex.js'; * 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 6ee849a16..4e1cec0f4 100644 --- a/rearg.js +++ b/rearg.js @@ -1,6 +1,5 @@ -import baseFlatten from './_baseFlatten.js'; -import baseRest from './_baseRest.js'; import createWrap from './_createWrap.js'; +import flatRest from './_flatRest.js'; /** Used to compose bitmasks for function metadata. */ var REARG_FLAG = 256; @@ -27,8 +26,8 @@ var REARG_FLAG = 256; * 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); }); export default rearg; diff --git a/sample.js b/sample.js index 94ec4e7c6..4a5e5ffe5 100644 --- a/sample.js +++ b/sample.js @@ -1,4 +1,4 @@ -import baseRandom from './_baseRandom.js'; +import arraySample from './_arraySample.js'; import isArrayLike from './isArrayLike.js'; import values from './values.js'; @@ -17,10 +17,7 @@ import values from './values.js'; * // => 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)); } export default sample; diff --git a/sampleSize.js b/sampleSize.js index 88226010f..7be10055b 100644 --- a/sampleSize.js +++ b/sampleSize.js @@ -1,8 +1,8 @@ -import baseClamp from './_baseClamp.js'; -import baseRandom from './_baseRandom.js'; +import arraySampleSize from './_arraySampleSize.js'; +import isArrayLike from './isArrayLike.js'; import isIterateeCall from './_isIterateeCall.js'; -import toArray from './toArray.js'; import toInteger from './toInteger.js'; +import values from './values.js'; /** * Gets `n` random elements at unique keys from `collection` up to the @@ -25,25 +25,12 @@ import toInteger from './toInteger.js'; * // => [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); } export default sampleSize; diff --git a/shuffle.js b/shuffle.js index 38b221aed..8698ed1db 100644 --- a/shuffle.js +++ b/shuffle.js @@ -1,7 +1,7 @@ -import sampleSize from './sampleSize.js'; - -/** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = 4294967295; +import copyArray from './_copyArray.js'; +import isArrayLike from './isArrayLike.js'; +import shuffleSelf from './_shuffleSelf.js'; +import values from './values.js'; /** * Creates an array of shuffled values, using a version of the @@ -19,7 +19,10 @@ var MAX_ARRAY_LENGTH = 4294967295; * // => [4, 1, 3, 2] */ function shuffle(collection) { - return sampleSize(collection, MAX_ARRAY_LENGTH); + return shuffleSelf(isArrayLike(collection) + ? copyArray(collection) + : values(collection) + ); } export default shuffle; diff --git a/sortBy.js b/sortBy.js index 99cc078d3..e37cd2ca9 100644 --- a/sortBy.js +++ b/sortBy.js @@ -26,16 +26,11 @@ import isIterateeCall from './_isIterateeCall.js'; * { '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 bf290bb1b..07d32c67c 100644 --- a/template.js +++ b/template.js @@ -86,7 +86,8 @@ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; * 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 3f7acda10..77169d8f0 100644 --- a/unescape.js +++ b/unescape.js @@ -7,7 +7,7 @@ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, /** * 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 be15c980b..ec7a90afd 100644 --- a/uniq.js +++ b/uniq.js @@ -3,8 +3,9 @@ import baseUniq from './_baseUniq.js'; /** * 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 d828b6dad..e4c124f7f 100644 --- a/uniqBy.js +++ b/uniqBy.js @@ -4,7 +4,9 @@ import baseUniq from './_baseUniq.js'; /** * 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 e72388d9a..437f3860f 100644 --- a/uniqWith.js +++ b/uniqWith.js @@ -2,8 +2,9 @@ import baseUniq from './_baseUniq.js'; /** * 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 a508e907e..f54af4fcb 100644 --- a/wrapperAt.js +++ b/wrapperAt.js @@ -1,8 +1,7 @@ import LazyWrapper from './_LazyWrapper.js'; import LodashWrapper from './_LodashWrapper.js'; import baseAt from './_baseAt.js'; -import baseFlatten from './_baseFlatten.js'; -import baseRest from './_baseRest.js'; +import flatRest from './_flatRest.js'; import isIndex from './_isIndex.js'; import thru from './thru.js'; @@ -22,8 +21,7 @@ import thru from './thru.js'; * _(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 1e57f7949..b2053e79b 100644 --- a/xorBy.js +++ b/xorBy.js @@ -8,8 +8,9 @@ import last from './last.js'; /** * 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 fef8f66ae..6815283dd 100644 --- a/xorWith.js +++ b/xorWith.js @@ -6,8 +6,9 @@ import last from './last.js'; /** * 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 _