From 75c633becb4087a11114feecdbf73745541302b5 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 16 Dec 2015 17:52:15 -0800 Subject: [PATCH] Bump to v3.10.0. --- LICENSE.txt => LICENSE | 0 README.md | 6 +- array/chunk.js | 11 +- array/difference.js | 6 +- array/indexOf.js | 9 +- array/intersection.js | 2 +- array/pull.js | 2 +- array/union.js | 2 +- array/uniq.js | 7 +- array/without.js | 2 +- array/xor.js | 4 +- chain.js | 3 +- chain/concat.js | 3 + chain/lodash.js | 72 +- chain/wrapperCommit.js | 6 +- chain/wrapperConcat.js | 31 + chain/wrapperPlant.js | 8 +- chain/wrapperReverse.js | 18 +- collection/every.js | 2 +- collection/includes.js | 9 +- collection/invoke.js | 5 +- collection/reduce.js | 3 +- collection/some.js | 2 +- collection/sortBy.js | 5 +- collection/sortByOrder.js | 15 +- function.js | 3 +- function/ary.js | 7 +- function/before.js | 5 +- function/debounce.js | 46 +- function/memoize.js | 2 +- function/modArgs.js | 56 ++ function/rearg.js | 5 +- function/throttle.js | 12 +- function/wrap.js | 5 +- internal/LazyWrapper.js | 7 +- internal/arrayConcat.js | 28 + internal/arrayPush.js | 23 + internal/arraySum.js | 8 +- internal/baseClone.js | 4 +- internal/baseCreate.js | 5 +- internal/baseDifference.js | 5 +- internal/baseFlatten.js | 23 +- internal/baseIsEqualDeep.js | 2 +- internal/baseMerge.js | 4 +- internal/baseMergeDeep.js | 2 +- internal/baseRandom.js | 8 +- internal/baseToString.js | 3 - internal/baseUniq.js | 5 +- internal/baseWrapperValue.js | 15 +- internal/binaryIndexBy.js | 8 +- internal/bufferClone.js | 46 +- internal/compareAscending.js | 4 +- internal/compareMultiple.js | 17 +- internal/composeArgs.js | 2 +- internal/createAggregator.js | 7 +- internal/createAssigner.js | 5 +- internal/createCache.js | 8 +- internal/createCtorWrapper.js | 4 +- internal/createCurry.js | 7 +- internal/createDefaults.js | 26 + internal/createExtremum.js | 9 +- internal/createFlow.js | 20 +- internal/createHybridWrapper.js | 12 +- internal/createPadding.js | 8 +- internal/createPartial.js | 5 +- internal/createPartialWrapper.js | 2 +- internal/createRound.js | 29 + internal/createWrapper.js | 6 +- internal/equalByTag.js | 2 +- internal/escapeRegExpChar.js | 41 + internal/escapeStringChar.js | 3 +- internal/getView.js | 4 +- internal/isIndex.js | 2 +- internal/isLength.js | 4 +- internal/lazyClone.js | 12 +- internal/lazyValue.js | 59 +- internal/mergeDefaults.js | 19 + internal/shimIsPlainObject.js | 53 -- lang/isArguments.js | 16 +- lang/isArray.js | 2 +- lang/isBoolean.js | 2 +- lang/isDate.js | 2 +- lang/isElement.js | 20 +- lang/isError.js | 2 +- lang/isFinite.js | 11 +- lang/isFunction.js | 13 +- lang/isNative.js | 15 +- lang/isNumber.js | 2 +- lang/isPlainObject.js | 40 +- lang/isRegExp.js | 6 +- lang/isString.js | 2 +- lang/isTypedArray.js | 2 +- main.js | 1278 ++++++++++++++++-------------- math.js | 5 +- math/ceil.js | 26 + math/floor.js | 26 + math/round.js | 26 + math/sum.js | 13 +- number/inRange.js | 5 +- number/random.js | 5 +- object.js | 3 +- object/assign.js | 2 +- object/create.js | 5 +- object/defaults.js | 14 +- object/defaultsDeep.js | 24 + object/invert.js | 5 +- object/keys.js | 7 +- object/transform.js | 5 +- package.json | 2 +- string/escapeRegExp.js | 13 +- string/pad.js | 12 +- string/parseInt.js | 37 +- string/repeat.js | 8 +- string/template.js | 4 +- string/trunc.js | 5 +- string/words.js | 5 +- support.js | 26 +- utility/callback.js | 5 +- utility/mixin.js | 12 +- utility/range.js | 11 +- utility/times.js | 8 +- 121 files changed, 1504 insertions(+), 1168 deletions(-) rename LICENSE.txt => LICENSE (100%) create mode 100644 chain/concat.js create mode 100644 chain/wrapperConcat.js create mode 100644 function/modArgs.js create mode 100644 internal/arrayConcat.js create mode 100644 internal/arrayPush.js create mode 100644 internal/createDefaults.js create mode 100644 internal/createRound.js create mode 100644 internal/escapeRegExpChar.js create mode 100644 internal/mergeDefaults.js delete mode 100644 internal/shimIsPlainObject.js create mode 100644 math/ceil.js create mode 100644 math/floor.js create mode 100644 math/round.js create mode 100644 object/defaultsDeep.js diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/README.md b/README.md index 2e2f9e49f..938c2855a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# lodash v3.9.3 +# lodash v3.10.0 The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) exported as [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) modules. @@ -13,8 +13,8 @@ $ lodash modern exports=amd -d -o ./main.js Using bower or volo: ```bash -$ bower i lodash#3.9.3-amd -$ volo add lodash/3.9.3-amd +$ bower i lodash#3.10.0-amd +$ volo add lodash/3.10.0-amd ``` Defining a build as `'lodash'`. diff --git a/array/chunk.js b/array/chunk.js index 44124e5f7..1cd503067 100644 --- a/array/chunk.js +++ b/array/chunk.js @@ -1,10 +1,9 @@ define(['../internal/baseSlice', '../internal/isIterateeCall'], function(baseSlice, isIterateeCall) { - /** Native method references. */ - var ceil = Math.ceil; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max; + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeMax = Math.max; /** * Creates an array of elements split into groups the length of `size`. @@ -30,12 +29,12 @@ define(['../internal/baseSlice', '../internal/isIterateeCall'], function(baseSli if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(+size || 1, 1); + size = nativeMax(nativeFloor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, - result = Array(ceil(length / size)); + result = Array(nativeCeil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); diff --git a/array/difference.js b/array/difference.js index 85fc9a326..5ca1e4294 100644 --- a/array/difference.js +++ b/array/difference.js @@ -1,8 +1,8 @@ -define(['../internal/baseDifference', '../internal/baseFlatten', '../internal/isArrayLike', '../function/restParam'], function(baseDifference, baseFlatten, isArrayLike, restParam) { +define(['../internal/baseDifference', '../internal/baseFlatten', '../internal/isArrayLike', '../internal/isObjectLike', '../function/restParam'], function(baseDifference, baseFlatten, isArrayLike, isObjectLike, restParam) { /** * Creates an array of unique `array` values not included in the other - * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -17,7 +17,7 @@ define(['../internal/baseDifference', '../internal/baseFlatten', '../internal/is * // => [1, 3] */ var difference = restParam(function(array, values) { - return isArrayLike(array) + return (isObjectLike(array) && isArrayLike(array)) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); diff --git a/array/indexOf.js b/array/indexOf.js index 763e2d8d7..1a5aad3d4 100644 --- a/array/indexOf.js +++ b/array/indexOf.js @@ -5,7 +5,7 @@ define(['../internal/baseIndexOf', '../internal/binaryIndex'], function(baseInde /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` * performs a faster binary search. @@ -39,10 +39,9 @@ define(['../internal/baseIndexOf', '../internal/binaryIndex'], function(baseInde if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; } else if (fromIndex) { - var index = binaryIndex(array, value), - other = array[index]; - - if (value === value ? (value === other) : (other !== other)) { + var index = binaryIndex(array, value); + if (index < length && + (value === value ? (value === array[index]) : (array[index] !== array[index]))) { return index; } return -1; diff --git a/array/intersection.js b/array/intersection.js index 1511d7fb7..ceb20011f 100644 --- a/array/intersection.js +++ b/array/intersection.js @@ -2,7 +2,7 @@ define(['../internal/baseIndexOf', '../internal/cacheIndexOf', '../internal/crea /** * Creates an array of unique values that are included in all of the provided - * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static diff --git a/array/pull.js b/array/pull.js index ed0af99e4..b40decdc4 100644 --- a/array/pull.js +++ b/array/pull.js @@ -8,7 +8,7 @@ define(['../internal/baseIndexOf'], function(baseIndexOf) { /** * Removes all provided values from `array` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. diff --git a/array/union.js b/array/union.js index f5b9aab06..1dd3f0b5e 100644 --- a/array/union.js +++ b/array/union.js @@ -2,7 +2,7 @@ define(['../internal/baseFlatten', '../internal/baseUniq', '../function/restPara /** * Creates an array of unique values, in order, from all of the provided arrays - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static diff --git a/array/uniq.js b/array/uniq.js index 1e2dd27f9..84d31e179 100644 --- a/array/uniq.js +++ b/array/uniq.js @@ -1,8 +1,11 @@ define(['../internal/baseCallback', '../internal/baseUniq', '../internal/isIterateeCall', '../internal/sortedUniq'], function(baseCallback, baseUniq, isIterateeCall, sortedUniq) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurence of each element * is kept. Providing `true` for `isSorted` performs a faster search algorithm * for sorted arrays. If an iteratee function is provided it is invoked for @@ -56,7 +59,7 @@ define(['../internal/baseCallback', '../internal/baseUniq', '../internal/isItera } if (isSorted != null && typeof isSorted != 'boolean') { thisArg = iteratee; - iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; isSorted = false; } iteratee = iteratee == null ? iteratee : baseCallback(iteratee, thisArg, 3); diff --git a/array/without.js b/array/without.js index 1c55b87dd..8bc4aa52d 100644 --- a/array/without.js +++ b/array/without.js @@ -2,7 +2,7 @@ define(['../internal/baseDifference', '../internal/isArrayLike', '../function/re /** * Creates an array excluding all provided values using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static diff --git a/array/xor.js b/array/xor.js index 8d90ba6b2..345368a0a 100644 --- a/array/xor.js +++ b/array/xor.js @@ -1,4 +1,4 @@ -define(['../internal/baseDifference', '../internal/baseUniq', '../internal/isArrayLike'], function(baseDifference, baseUniq, isArrayLike) { +define(['../internal/arrayPush', '../internal/baseDifference', '../internal/baseUniq', '../internal/isArrayLike'], function(arrayPush, baseDifference, baseUniq, isArrayLike) { /** * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) @@ -22,7 +22,7 @@ define(['../internal/baseDifference', '../internal/baseUniq', '../internal/isArr var array = arguments[index]; if (isArrayLike(array)) { var result = result - ? baseDifference(result, array).concat(baseDifference(array, result)) + ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; } } diff --git a/chain.js b/chain.js index 381fe755e..35b9ddf0f 100644 --- a/chain.js +++ b/chain.js @@ -1,7 +1,8 @@ -define(['./chain/chain', './chain/commit', './chain/lodash', './chain/plant', './chain/reverse', './chain/run', './chain/tap', './chain/thru', './chain/toJSON', './chain/toString', './chain/value', './chain/valueOf', './chain/wrapperChain'], function(chain, commit, lodash, plant, reverse, run, tap, thru, toJSON, toString, value, valueOf, wrapperChain) { +define(['./chain/chain', './chain/commit', './chain/concat', './chain/lodash', './chain/plant', './chain/reverse', './chain/run', './chain/tap', './chain/thru', './chain/toJSON', './chain/toString', './chain/value', './chain/valueOf', './chain/wrapperChain'], function(chain, commit, concat, lodash, plant, reverse, run, tap, thru, toJSON, toString, value, valueOf, wrapperChain) { return { 'chain': chain, 'commit': commit, + 'concat': concat, 'lodash': lodash, 'plant': plant, 'reverse': reverse, diff --git a/chain/concat.js b/chain/concat.js new file mode 100644 index 000000000..da9351896 --- /dev/null +++ b/chain/concat.js @@ -0,0 +1,3 @@ +define(["./wrapperConcat"], function(wrapperConcat) { + return wrapperConcat; +}); diff --git a/chain/lodash.js b/chain/lodash.js index e76777f75..ab022c957 100644 --- a/chain/lodash.js +++ b/chain/lodash.js @@ -9,15 +9,16 @@ define(['../internal/LazyWrapper', '../internal/LodashWrapper', '../internal/bas /** * Creates a `lodash` object which wraps `value` to enable implicit chaining. * Methods that operate on and return arrays, collections, and functions can - * be chained together. Methods that return a boolean or single value will - * automatically end the chain returning the unwrapped value. Explicit chaining - * may be enabled using `_.chain`. The execution of chained methods is lazy, - * that is, execution is deferred until `_#value` is implicitly or explicitly - * called. + * be chained together. Methods that retrieve a single value or may return a + * primitive value will automatically end the chain returning the unwrapped + * value. Explicit chaining may be enabled using `_.chain`. The execution of + * chained methods is lazy, that is, execution is deferred until `_#value` + * is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization that merges iteratees to avoid creating intermediate - * arrays and reduce the number of iteratee executions. + * fusion is an optimization strategy which merge iteratee calls; this can help + * to avoid the creation of intermediate data structures and greatly reduce the + * number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. @@ -40,36 +41,37 @@ define(['../internal/LazyWrapper', '../internal/LodashWrapper', '../internal/bas * The chainable wrapper methods are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, - * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, - * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, - * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, - * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, - * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, - * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, - * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, - * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, - * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, - * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, - * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, - * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, + * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, + * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, + * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, + * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, + * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, + * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, - * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, - * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, - * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, - * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, - * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, - * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, - * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, - * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, - * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, + * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, + * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, + * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, + * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, + * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, + * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, + * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, + * `unescape`, `uniqueId`, `value`, and `words` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. diff --git a/chain/wrapperCommit.js b/chain/wrapperCommit.js index 05e9826ac..576ec1c30 100644 --- a/chain/wrapperCommit.js +++ b/chain/wrapperCommit.js @@ -10,16 +10,16 @@ define(['../internal/LodashWrapper'], function(LodashWrapper) { * @example * * var array = [1, 2]; - * var wrapper = _(array).push(3); + * var wrapped = _(array).push(3); * * console.log(array); * // => [1, 2] * - * wrapper = wrapper.commit(); + * wrapped = wrapped.commit(); * console.log(array); * // => [1, 2, 3] * - * wrapper.last(); + * wrapped.last(); * // => 3 * * console.log(array); diff --git a/chain/wrapperConcat.js b/chain/wrapperConcat.js new file mode 100644 index 000000000..926c7e7b1 --- /dev/null +++ b/chain/wrapperConcat.js @@ -0,0 +1,31 @@ +define(['../internal/arrayConcat', '../internal/baseFlatten', '../lang/isArray', '../function/restParam', '../internal/toObject'], function(arrayConcat, baseFlatten, isArray, restParam, toObject) { + + /** + * Creates a new array joining a wrapped array with any additional arrays + * and/or values. + * + * @name concat + * @memberOf _ + * @category Chain + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var wrapped = _(array).concat(2, [3], [[4]]); + * + * console.log(wrapped.value()); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [toObject(array)], values); + }); + }); + + return wrapperConcat; +}); diff --git a/chain/wrapperPlant.js b/chain/wrapperPlant.js index 51d2168ab..d30ebb627 100644 --- a/chain/wrapperPlant.js +++ b/chain/wrapperPlant.js @@ -10,17 +10,17 @@ define(['../internal/baseLodash', '../internal/wrapperClone'], function(baseLoda * @example * * var array = [1, 2]; - * var wrapper = _(array).map(function(value) { + * var wrapped = _(array).map(function(value) { * return Math.pow(value, 2); * }); * * var other = [3, 4]; - * var otherWrapper = wrapper.plant(other); + * var otherWrapped = wrapped.plant(other); * - * otherWrapper.value(); + * otherWrapped.value(); * // => [9, 16] * - * wrapper.value(); + * wrapped.value(); * // => [1, 4] */ function wrapperPlant(value) { diff --git a/chain/wrapperReverse.js b/chain/wrapperReverse.js index 072da4396..2a4a51ec9 100644 --- a/chain/wrapperReverse.js +++ b/chain/wrapperReverse.js @@ -1,5 +1,8 @@ define(['../internal/LazyWrapper', '../internal/LodashWrapper', './thru'], function(LazyWrapper, LodashWrapper, thru) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Reverses the wrapped array so the first element becomes the last, the * second element becomes the second to last, and so on. @@ -22,15 +25,20 @@ define(['../internal/LazyWrapper', '../internal/LodashWrapper', './thru'], funct */ function wrapperReverse() { var value = this.__wrapped__; + + var interceptor = function(value) { + return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse(); + }; if (value instanceof LazyWrapper) { + var wrapped = value; if (this.__actions__.length) { - value = new LazyWrapper(this); + wrapped = new LazyWrapper(this); } - return new LodashWrapper(value.reverse(), this.__chain__); + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(wrapped, this.__chain__); } - return this.thru(function(value) { - return value.reverse(); - }); + return this.thru(interceptor); } return wrapperReverse; diff --git a/collection/every.js b/collection/every.js index 6b2a4dbfa..11eb21281 100644 --- a/collection/every.js +++ b/collection/every.js @@ -54,7 +54,7 @@ define(['../internal/arrayEvery', '../internal/baseCallback', '../internal/baseE function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = baseCallback(predicate, thisArg, 3); diff --git a/collection/includes.js b/collection/includes.js index cf77f0ea6..12c57a974 100644 --- a/collection/includes.js +++ b/collection/includes.js @@ -5,7 +5,7 @@ define(['../internal/baseIndexOf', '../internal/getLength', '../lang/isArray', ' /** * Checks if `value` is in `collection` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `collection`. * @@ -38,17 +38,14 @@ define(['../internal/baseIndexOf', '../internal/getLength', '../lang/isArray', ' collection = values(collection); length = collection.length; } - if (!length) { - return false; - } if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; } else { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) - ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) - : (baseIndexOf(collection, target, fromIndex) > -1); + ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) + : (!!length && baseIndexOf(collection, target, fromIndex) > -1); } return includes; diff --git a/collection/invoke.js b/collection/invoke.js index 36025ebb9..f5273cc84 100644 --- a/collection/invoke.js +++ b/collection/invoke.js @@ -1,5 +1,8 @@ define(['../internal/baseEach', '../internal/invokePath', '../internal/isArrayLike', '../internal/isKey', '../function/restParam'], function(baseEach, invokePath, isArrayLike, isKey, restParam) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments @@ -29,7 +32,7 @@ define(['../internal/baseEach', '../internal/invokePath', '../internal/isArrayLi result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; diff --git a/collection/reduce.js b/collection/reduce.js index 3b2789c40..78010130e 100644 --- a/collection/reduce.js +++ b/collection/reduce.js @@ -12,7 +12,8 @@ define(['../internal/arrayReduce', '../internal/baseEach', '../internal/createRe * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, + * and `sortByOrder` * * @static * @memberOf _ diff --git a/collection/some.js b/collection/some.js index 18f4308e7..f240f3cfa 100644 --- a/collection/some.js +++ b/collection/some.js @@ -55,7 +55,7 @@ define(['../internal/arraySome', '../internal/baseCallback', '../internal/baseSo function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = baseCallback(predicate, thisArg, 3); diff --git a/collection/sortBy.js b/collection/sortBy.js index 0958b118b..c312c83be 100644 --- a/collection/sortBy.js +++ b/collection/sortBy.js @@ -1,5 +1,8 @@ define(['../internal/baseCallback', '../internal/baseMap', '../internal/baseSortBy', '../internal/compareAscending', '../internal/isIterateeCall'], function(baseCallback, baseMap, baseSortBy, compareAscending, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through `iteratee`. This method performs @@ -53,7 +56,7 @@ define(['../internal/baseCallback', '../internal/baseMap', '../internal/baseSort return []; } if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } var index = -1; iteratee = baseCallback(iteratee, thisArg, 3); diff --git a/collection/sortByOrder.js b/collection/sortByOrder.js index c8899a600..cdaafc0cb 100644 --- a/collection/sortByOrder.js +++ b/collection/sortByOrder.js @@ -1,10 +1,13 @@ define(['../internal/baseSortByOrder', '../lang/isArray', '../internal/isIterateeCall'], function(baseSortByOrder, isArray, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * This method is like `_.sortByAll` except that it allows specifying the - * sort orders of the iteratees to sort by. A truthy value in `orders` will - * sort the corresponding property name in ascending order while a falsey - * value will sort it in descending order. + * sort orders of the iteratees to sort by. If `orders` is unspecified, all + * values are sorted in ascending order. Otherwise, a value is sorted in + * ascending order if its corresponding order is "asc", and descending if "desc". * * If a property name is provided for an iteratee the created `_.property` * style callback returns the property value of the given element. @@ -18,7 +21,7 @@ define(['../internal/baseSortByOrder', '../lang/isArray', '../internal/isIterate * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} orders The sort orders of `iteratees`. + * @param {boolean[]} [orders] The sort orders of `iteratees`. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example @@ -31,7 +34,7 @@ define(['../internal/baseSortByOrder', '../lang/isArray', '../internal/isIterate * ]; * * // sort by `user` in ascending order and by `age` in descending order - * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); + * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] */ function sortByOrder(collection, iteratees, orders, guard) { @@ -39,7 +42,7 @@ define(['../internal/baseSortByOrder', '../lang/isArray', '../internal/isIterate return []; } if (guard && isIterateeCall(iteratees, orders, guard)) { - orders = null; + orders = undefined; } if (!isArray(iteratees)) { iteratees = iteratees == null ? [] : [iteratees]; diff --git a/function.js b/function.js index 86939dff7..d00110fcd 100644 --- a/function.js +++ b/function.js @@ -1,4 +1,4 @@ -define(['./function/after', './function/ary', './function/backflow', './function/before', './function/bind', './function/bindAll', './function/bindKey', './function/compose', './function/curry', './function/curryRight', './function/debounce', './function/defer', './function/delay', './function/flow', './function/flowRight', './function/memoize', './function/negate', './function/once', './function/partial', './function/partialRight', './function/rearg', './function/restParam', './function/spread', './function/throttle', './function/wrap'], function(after, ary, backflow, before, bind, bindAll, bindKey, compose, curry, curryRight, debounce, defer, delay, flow, flowRight, memoize, negate, once, partial, partialRight, rearg, restParam, spread, throttle, wrap) { +define(['./function/after', './function/ary', './function/backflow', './function/before', './function/bind', './function/bindAll', './function/bindKey', './function/compose', './function/curry', './function/curryRight', './function/debounce', './function/defer', './function/delay', './function/flow', './function/flowRight', './function/memoize', './function/modArgs', './function/negate', './function/once', './function/partial', './function/partialRight', './function/rearg', './function/restParam', './function/spread', './function/throttle', './function/wrap'], function(after, ary, backflow, before, bind, bindAll, bindKey, compose, curry, curryRight, debounce, defer, delay, flow, flowRight, memoize, modArgs, negate, once, partial, partialRight, rearg, restParam, spread, throttle, wrap) { return { 'after': after, 'ary': ary, @@ -16,6 +16,7 @@ define(['./function/after', './function/ary', './function/backflow', './function 'flow': flow, 'flowRight': flowRight, 'memoize': memoize, + 'modArgs': modArgs, 'negate': negate, 'once': once, 'partial': partial, diff --git a/function/ary.js b/function/ary.js index 5243bf806..d9c19d888 100644 --- a/function/ary.js +++ b/function/ary.js @@ -1,5 +1,8 @@ define(['../internal/createWrapper', '../internal/isIterateeCall'], function(createWrapper, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used to compose bitmasks for wrapper metadata. */ var ARY_FLAG = 128; @@ -24,10 +27,10 @@ define(['../internal/createWrapper', '../internal/isIterateeCall'], function(cre */ function ary(func, n, guard) { if (guard && isIterateeCall(func, n, guard)) { - n = null; + n = undefined; } n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); - return createWrapper(func, ARY_FLAG, null, null, null, null, n); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } return ary; diff --git a/function/before.js b/function/before.js index 07e8f38b6..b77bdcdbb 100644 --- a/function/before.js +++ b/function/before.js @@ -1,5 +1,8 @@ define([], function() { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -35,7 +38,7 @@ define([], function() { result = func.apply(this, arguments); } if (n <= 1) { - func = null; + func = undefined; } return result; }; diff --git a/function/debounce.js b/function/debounce.js index 9f31a40dd..cfc443c14 100644 --- a/function/debounce.js +++ b/function/debounce.js @@ -92,9 +92,9 @@ define(['../lang/isObject', '../date/now'], function(isObject, now) { var leading = true; trailing = false; } else if (isObject(options)) { - leading = options.leading; + leading = !!options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); - trailing = 'trailing' in options ? options.trailing : trailing; + trailing = 'trailing' in options ? !!options.trailing : trailing; } function cancel() { @@ -104,41 +104,35 @@ define(['../lang/isObject', '../date/now'], function(isObject, now) { if (maxTimeoutId) { clearTimeout(maxTimeoutId); } + lastCalled = 0; maxTimeoutId = timeoutId = trailingCall = undefined; } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailing, timeoutId); } function debounced() { @@ -178,7 +172,7 @@ define(['../lang/isObject', '../date/now'], function(isObject, now) { result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } return result; } diff --git a/function/memoize.js b/function/memoize.js index f2eaf5a19..86ba5b03c 100644 --- a/function/memoize.js +++ b/function/memoize.js @@ -13,7 +13,7 @@ define(['../internal/MapCache'], function(MapCache) { * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) * method interface of `get`, `has`, and `set`. * * @static diff --git a/function/modArgs.js b/function/modArgs.js new file mode 100644 index 000000000..556203784 --- /dev/null +++ b/function/modArgs.js @@ -0,0 +1,56 @@ +define(['../internal/arrayEvery', '../internal/baseFlatten', '../internal/baseIsFunction', './restParam'], function(arrayEvery, baseFlatten, baseIsFunction, restParam) { + + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /* Native method references for those with the same name as other `lodash` methods. */ + var nativeMin = Math.min; + + /** + * Creates a function that runs each argument through a corresponding + * transform function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms] The functions to transform + * arguments, specified as individual functions or arrays of functions. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var modded = _.modArgs(function(x, y) { + * return [x, y]; + * }, square, doubled); + * + * modded(1, 2); + * // => [1, 4] + * + * modded(5, 10); + * // => [25, 20] + */ + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + + return modArgs; +}); diff --git a/function/rearg.js b/function/rearg.js index e41eee197..356077426 100644 --- a/function/rearg.js +++ b/function/rearg.js @@ -1,5 +1,8 @@ define(['../internal/baseFlatten', '../internal/createWrapper', './restParam'], function(baseFlatten, createWrapper, restParam) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used to compose bitmasks for wrapper metadata. */ var REARG_FLAG = 256; @@ -32,7 +35,7 @@ define(['../internal/baseFlatten', '../internal/createWrapper', './restParam'], * // => [3, 6, 9] */ var rearg = restParam(function(func, indexes) { - return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); }); return rearg; diff --git a/function/throttle.js b/function/throttle.js index 9af2c15e4..b098bf68b 100644 --- a/function/throttle.js +++ b/function/throttle.js @@ -3,13 +3,6 @@ define(['./debounce', '../lang/isObject'], function(debounce, isObject) { /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; - /** Used as an internal `_.debounce` options object by `_.throttle`. */ - var debounceOptions = { - 'leading': false, - 'maxWait': 0, - 'trailing': false - }; - /** * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds. The throttled function comes with a `cancel` @@ -62,10 +55,7 @@ define(['./debounce', '../lang/isObject'], function(debounce, isObject) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } - debounceOptions.leading = leading; - debounceOptions.maxWait = +wait; - debounceOptions.trailing = trailing; - return debounce(func, wait, debounceOptions); + return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); } return throttle; diff --git a/function/wrap.js b/function/wrap.js index d2bfa7698..8d7156ded 100644 --- a/function/wrap.js +++ b/function/wrap.js @@ -1,5 +1,8 @@ define(['../internal/createWrapper', '../utility/identity'], function(createWrapper, identity) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used to compose bitmasks for wrapper metadata. */ var PARTIAL_FLAG = 32; @@ -26,7 +29,7 @@ define(['../internal/createWrapper', '../utility/identity'], function(createWrap */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; - return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []); } return wrap; diff --git a/internal/LazyWrapper.js b/internal/LazyWrapper.js index c564a9f89..3e985376d 100644 --- a/internal/LazyWrapper.js +++ b/internal/LazyWrapper.js @@ -11,13 +11,12 @@ define(['./baseCreate', './baseLodash'], function(baseCreate, baseLodash) { */ function LazyWrapper(value) { this.__wrapped__ = value; - this.__actions__ = null; + this.__actions__ = []; this.__dir__ = 1; - this.__dropCount__ = 0; this.__filtered__ = false; - this.__iteratees__ = null; + this.__iteratees__ = []; this.__takeCount__ = POSITIVE_INFINITY; - this.__views__ = null; + this.__views__ = []; } LazyWrapper.prototype = baseCreate(baseLodash.prototype); diff --git a/internal/arrayConcat.js b/internal/arrayConcat.js new file mode 100644 index 000000000..a2cd19f71 --- /dev/null +++ b/internal/arrayConcat.js @@ -0,0 +1,28 @@ +define([], function() { + + /** + * Creates a new array joining `array` with `other`. + * + * @private + * @param {Array} array The array to join. + * @param {Array} other The other array to join. + * @returns {Array} Returns the new concatenated array. + */ + function arrayConcat(array, other) { + var index = -1, + length = array.length, + othIndex = -1, + othLength = other.length, + result = Array(length + othLength); + + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + + return arrayConcat; +}); diff --git a/internal/arrayPush.js b/internal/arrayPush.js new file mode 100644 index 000000000..6566d2506 --- /dev/null +++ b/internal/arrayPush.js @@ -0,0 +1,23 @@ +define([], function() { + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + return arrayPush; +}); diff --git a/internal/arraySum.js b/internal/arraySum.js index 9c5ac0baa..f48a3c7e6 100644 --- a/internal/arraySum.js +++ b/internal/arraySum.js @@ -1,18 +1,20 @@ define([], function() { /** - * A specialized version of `_.sum` for arrays without support for iteratees. + * A specialized version of `_.sum` for arrays without support for callback + * shorthands and `this` binding.. * * @private * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the sum. */ - function arraySum(array) { + function arraySum(array, iteratee) { var length = array.length, result = 0; while (length--) { - result += +array[length] || 0; + result += +iteratee(array[length]) || 0; } return result; } diff --git a/internal/baseClone.js b/internal/baseClone.js index 00fa9a019..71a842325 100644 --- a/internal/baseClone.js +++ b/internal/baseClone.js @@ -48,7 +48,7 @@ define(['./arrayCopy', './arrayEach', './baseAssign', './baseForOwn', './initClo var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; @@ -99,7 +99,7 @@ define(['./arrayCopy', './arrayEach', './baseAssign', './baseForOwn', './initClo : (object ? value : {}); } } - // Check for circular references and return corresponding clone. + // Check for circular references and return its corresponding clone. stackA || (stackA = []); stackB || (stackB = []); diff --git a/internal/baseCreate.js b/internal/baseCreate.js index 6b41af706..f88b921ec 100644 --- a/internal/baseCreate.js +++ b/internal/baseCreate.js @@ -1,5 +1,8 @@ define(['../lang/isObject'], function(isObject) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * The base implementation of `_.create` without support for assigning * properties to the created object. @@ -14,7 +17,7 @@ define(['../lang/isObject'], function(isObject) { if (isObject(prototype)) { object.prototype = prototype; var result = new object; - object.prototype = null; + object.prototype = undefined; } return result || {}; }; diff --git a/internal/baseDifference.js b/internal/baseDifference.js index 1ed64e4ac..3fb7edd6a 100644 --- a/internal/baseDifference.js +++ b/internal/baseDifference.js @@ -1,5 +1,8 @@ define(['./baseIndexOf', './cacheIndexOf', './createCache'], function(baseIndexOf, cacheIndexOf, createCache) { + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** * The base implementation of `_.difference` which accepts a single array * of values to exclude. @@ -19,7 +22,7 @@ define(['./baseIndexOf', './cacheIndexOf', './createCache'], function(baseIndexO var index = -1, indexOf = baseIndexOf, isCommon = true, - cache = (isCommon && values.length >= 200) ? createCache(values) : null, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, valuesLength = values.length; if (cache) { diff --git a/internal/baseFlatten.js b/internal/baseFlatten.js index f1ef6d84f..380e4196d 100644 --- a/internal/baseFlatten.js +++ b/internal/baseFlatten.js @@ -1,4 +1,4 @@ -define(['../lang/isArguments', '../lang/isArray', './isArrayLike', './isObjectLike'], function(isArguments, isArray, isArrayLike, isObjectLike) { +define(['./arrayPush', '../lang/isArguments', '../lang/isArray', './isArrayLike', './isObjectLike'], function(arrayPush, isArguments, isArray, isArrayLike, isObjectLike) { /** * The base implementation of `_.flatten` with added support for restricting @@ -8,13 +8,14 @@ define(['../lang/isArguments', '../lang/isArray', './isArrayLike', './isObjectLi * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isDeep, isStrict) { + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, - length = array.length, - resIndex = -1, - result = []; + length = array.length; while (++index < length) { var value = array[index]; @@ -22,16 +23,12 @@ define(['../lang/isArguments', '../lang/isArray', './isArrayLike', './isObjectLi (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict); - } - var valIndex = -1, - valLength = value.length; - - while (++valIndex < valLength) { - result[++resIndex] = value[valIndex]; + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); } } else if (!isStrict) { - result[++resIndex] = value; + result[result.length] = value; } } return result; diff --git a/internal/baseIsEqualDeep.js b/internal/baseIsEqualDeep.js index fdc03945b..82f967c3c 100644 --- a/internal/baseIsEqualDeep.js +++ b/internal/baseIsEqualDeep.js @@ -12,7 +12,7 @@ define(['./equalArrays', './equalByTag', './equalObjects', '../lang/isArray', '. var hasOwnProperty = objectProto.hasOwnProperty; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/internal/baseMerge.js b/internal/baseMerge.js index fe6519b7e..1e25af801 100644 --- a/internal/baseMerge.js +++ b/internal/baseMerge.js @@ -10,7 +10,7 @@ define(['./arrayEach', './baseMergeDeep', '../lang/isArray', './isArrayLike', '. * @private * @param {Object} object The destination object. * @param {Object} source The source object. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns `object`. @@ -20,7 +20,7 @@ define(['./arrayEach', './baseMergeDeep', '../lang/isArray', './isArrayLike', '. return object; } var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), - props = isSrcArr ? null : keys(source); + props = isSrcArr ? undefined : keys(source); arrayEach(props || source, function(srcValue, key) { if (props) { diff --git a/internal/baseMergeDeep.js b/internal/baseMergeDeep.js index d9d13921a..a807f2549 100644 --- a/internal/baseMergeDeep.js +++ b/internal/baseMergeDeep.js @@ -13,7 +13,7 @@ define(['./arrayCopy', '../lang/isArguments', '../lang/isArray', './isArrayLike' * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. diff --git a/internal/baseRandom.js b/internal/baseRandom.js index 0cfb4a993..f1495ae3f 100644 --- a/internal/baseRandom.js +++ b/internal/baseRandom.js @@ -1,10 +1,8 @@ define([], function() { - /** Native method references. */ - var floor = Math.floor; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeRandom = Math.random; + var nativeFloor = Math.floor, + nativeRandom = Math.random; /** * The base implementation of `_.random` without support for argument juggling @@ -16,7 +14,7 @@ define([], function() { * @returns {number} Returns the random number. */ function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + return min + nativeFloor(nativeRandom() * (max - min + 1)); } return baseRandom; diff --git a/internal/baseToString.js b/internal/baseToString.js index bccd2b79c..a93ab7391 100644 --- a/internal/baseToString.js +++ b/internal/baseToString.js @@ -9,9 +9,6 @@ define([], function() { * @returns {string} Returns the string. */ function baseToString(value) { - if (typeof value == 'string') { - return value; - } return value == null ? '' : (value + ''); } diff --git a/internal/baseUniq.js b/internal/baseUniq.js index acf8e5d3c..3cbf3a9f8 100644 --- a/internal/baseUniq.js +++ b/internal/baseUniq.js @@ -1,5 +1,8 @@ define(['./baseIndexOf', './cacheIndexOf', './createCache'], function(baseIndexOf, cacheIndexOf, createCache) { + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** * The base implementation of `_.uniq` without support for callback shorthands * and `this` binding. @@ -14,7 +17,7 @@ define(['./baseIndexOf', './cacheIndexOf', './createCache'], function(baseIndexO indexOf = baseIndexOf, length = array.length, isCommon = true, - isLarge = isCommon && length >= 200, + isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; diff --git a/internal/baseWrapperValue.js b/internal/baseWrapperValue.js index 4937457f9..255d956f4 100644 --- a/internal/baseWrapperValue.js +++ b/internal/baseWrapperValue.js @@ -1,10 +1,4 @@ -define(['./LazyWrapper'], function(LazyWrapper) { - - /** Used for native method references. */ - var arrayProto = Array.prototype; - - /** Native method references. */ - var push = arrayProto.push; +define(['./LazyWrapper', './arrayPush'], function(LazyWrapper, arrayPush) { /** * The base implementation of `wrapperValue` which returns the result of @@ -25,11 +19,8 @@ define(['./LazyWrapper'], function(LazyWrapper) { length = actions.length; while (++index < length) { - var args = [result], - action = actions[index]; - - push.apply(args, action.args); - result = action.func.apply(action.thisArg, args); + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([result], action.args)); } return result; } diff --git a/internal/binaryIndexBy.js b/internal/binaryIndexBy.js index 3c0119cd0..e86ed6f63 100644 --- a/internal/binaryIndexBy.js +++ b/internal/binaryIndexBy.js @@ -3,11 +3,9 @@ define([], function() { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; - /** Native method references. */ - var floor = Math.floor; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeMin = Math.min; + var nativeFloor = Math.floor, + nativeMin = Math.min; /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295, @@ -36,7 +34,7 @@ define([], function() { valIsUndef = value === undefined; while (low < high) { - var mid = floor((low + high) / 2), + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; diff --git a/internal/bufferClone.js b/internal/bufferClone.js index f3cb4a0a6..cfd586dc8 100644 --- a/internal/bufferClone.js +++ b/internal/bufferClone.js @@ -1,25 +1,8 @@ -define(['../utility/constant', './getNative', './root'], function(constant, getNative, root) { +define(['./root'], function(root) { /** Native method references. */ - var ArrayBuffer = getNative(root, 'ArrayBuffer'), - bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), - floor = Math.floor, - Uint8Array = getNative(root, 'Uint8Array'); - - /** Used to clone array buffers. */ - var Float64Array = (function() { - // Safari 5 errors when using an array buffer to initialize a typed array - // where the array buffer's `byteLength` is not a multiple of the typed - // array's `BYTES_PER_ELEMENT`. - try { - var func = getNative(root, 'Float64Array'), - result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) {} - return result || null; - }()); - - /** Used as the size, in bytes, of each `Float64Array` element. */ - var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; + var ArrayBuffer = root.ArrayBuffer, + Uint8Array = root.Uint8Array; /** * Creates a clone of the given array buffer. @@ -29,26 +12,11 @@ define(['../utility/constant', './getNative', './root'], function(constant, getN * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. - bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + var result = new ArrayBuffer(buffer.byteLength), + view = new Uint8Array(result); - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); - } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); - } - return result; - }; + view.set(new Uint8Array(buffer)); + return result; } return bufferClone; diff --git a/internal/compareAscending.js b/internal/compareAscending.js index 0f9be14d1..a0cafa9ce 100644 --- a/internal/compareAscending.js +++ b/internal/compareAscending.js @@ -5,8 +5,8 @@ define(['./baseCompareAscending'], function(baseCompareAscending) { * sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { diff --git a/internal/compareMultiple.js b/internal/compareMultiple.js index bd4dd5d23..aa19db96a 100644 --- a/internal/compareMultiple.js +++ b/internal/compareMultiple.js @@ -1,16 +1,16 @@ define(['./baseCompareAscending'], function(baseCompareAscending) { /** - * Used by `_.sortByOrder` to compare multiple properties of each element - * in a collection and stable sort them in the following order: + * Used by `_.sortByOrder` to compare multiple properties of a value to another + * and stable sort them. * - * If `orders` is unspecified, sort in ascending order for all properties. - * Otherwise, for each property, sort in ascending order if its corresponding value in - * orders is true, and descending order if false. + * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise, + * a value is sorted in ascending order if its corresponding order is "asc", and + * descending if "desc". * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @param {boolean[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ @@ -27,7 +27,8 @@ define(['./baseCompareAscending'], function(baseCompareAscending) { if (index >= ordersLength) { return result; } - return result * (orders[index] ? 1 : -1); + var order = orders[index]; + return result * ((order === 'asc' || order === true) ? 1 : -1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications diff --git a/internal/composeArgs.js b/internal/composeArgs.js index c8c329226..47ac1101d 100644 --- a/internal/composeArgs.js +++ b/internal/composeArgs.js @@ -19,7 +19,7 @@ define([], function() { argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, - result = Array(argsLength + leftLength); + result = Array(leftLength + argsLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; diff --git a/internal/createAggregator.js b/internal/createAggregator.js index 401e110d7..ede68ac9c 100644 --- a/internal/createAggregator.js +++ b/internal/createAggregator.js @@ -1,12 +1,7 @@ define(['./baseCallback', './baseEach', '../lang/isArray'], function(baseCallback, baseEach, isArray) { /** - * Creates a function that aggregates a collection, creating an accumulator - * object composed from the results of running each element in the collection - * through an iteratee. - * - * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, - * and `_.partition`. + * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. diff --git a/internal/createAssigner.js b/internal/createAssigner.js index 57807fd36..921cb16f0 100644 --- a/internal/createAssigner.js +++ b/internal/createAssigner.js @@ -4,10 +4,7 @@ define(['./bindCallback', './isIterateeCall', '../function/restParam'], function var undefined; /** - * Creates a function that assigns properties of source object(s) to a given - * destination object. - * - * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * Creates a `_.assign`, `_.defaults`, or `_.merge` function. * * @private * @param {Function} assigner The function to assign values. diff --git a/internal/createCache.js b/internal/createCache.js index adf6fc503..ef7440565 100644 --- a/internal/createCache.js +++ b/internal/createCache.js @@ -1,4 +1,4 @@ -define(['./SetCache', '../utility/constant', './getNative', './root'], function(SetCache, constant, getNative, root) { +define(['./SetCache', './getNative', './root'], function(SetCache, getNative, root) { /** Native method references. */ var Set = getNative(root, 'Set'); @@ -13,9 +13,9 @@ define(['./SetCache', '../utility/constant', './getNative', './root'], function( * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ - var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { - return new SetCache(values); - }; + function createCache(values) { + return (nativeCreate && Set) ? new SetCache(values) : null; + } return createCache; }); diff --git a/internal/createCtorWrapper.js b/internal/createCtorWrapper.js index 72df566a1..f4355549a 100644 --- a/internal/createCtorWrapper.js +++ b/internal/createCtorWrapper.js @@ -11,7 +11,7 @@ define(['./baseCreate', '../lang/isObject'], function(baseCreate, isObject) { function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. - // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -21,6 +21,8 @@ define(['./baseCreate', '../lang/isObject'], function(baseCreate, isObject) { case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); diff --git a/internal/createCurry.js b/internal/createCurry.js index 70d097e77..9f30502f9 100644 --- a/internal/createCurry.js +++ b/internal/createCurry.js @@ -1,5 +1,8 @@ define(['./createWrapper', './isIterateeCall'], function(createWrapper, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates a `_.curry` or `_.curryRight` function. * @@ -10,9 +13,9 @@ define(['./createWrapper', './isIterateeCall'], function(createWrapper, isIterat function createCurry(flag) { function curryFunc(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { - arity = null; + arity = undefined; } - var result = createWrapper(func, flag, null, null, null, null, null, arity); + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryFunc.placeholder; return result; } diff --git a/internal/createDefaults.js b/internal/createDefaults.js new file mode 100644 index 000000000..edab6d166 --- /dev/null +++ b/internal/createDefaults.js @@ -0,0 +1,26 @@ +define(['../function/restParam'], function(restParam) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** + * Creates a `_.defaults` or `_.defaultsDeep` function. + * + * @private + * @param {Function} assigner The function to assign values. + * @param {Function} customizer The function to customize assigned values. + * @returns {Function} Returns the new defaults function. + */ + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + + return createDefaults; +}); diff --git a/internal/createExtremum.js b/internal/createExtremum.js index 1c7d76b74..1d88a8058 100644 --- a/internal/createExtremum.js +++ b/internal/createExtremum.js @@ -1,4 +1,7 @@ -define(['./arrayExtremum', './baseCallback', './baseExtremum', './isIterateeCall', './toIterable'], function(arrayExtremum, baseCallback, baseExtremum, isIterateeCall, toIterable) { +define(['./arrayExtremum', './baseCallback', './baseExtremum', '../lang/isArray', './isIterateeCall', './toIterable'], function(arrayExtremum, baseCallback, baseExtremum, isArray, isIterateeCall, toIterable) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; /** * Creates a `_.max` or `_.min` function. @@ -11,11 +14,11 @@ define(['./arrayExtremum', './baseCallback', './baseExtremum', './isIterateeCall function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } iteratee = baseCallback(iteratee, thisArg, 3); if (iteratee.length == 1) { - collection = toIterable(collection); + collection = isArray(collection) ? collection : toIterable(collection); var result = arrayExtremum(collection, iteratee, comparator, exValue); if (!(collection.length && result === exValue)) { return result; diff --git a/internal/createFlow.js b/internal/createFlow.js index bdd93945e..5859d3506 100644 --- a/internal/createFlow.js +++ b/internal/createFlow.js @@ -1,11 +1,17 @@ define(['./LodashWrapper', './getData', './getFuncName', '../lang/isArray', './isLaziable'], function(LodashWrapper, getData, getFuncName, isArray, isLaziable) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used to compose bitmasks for wrapper metadata. */ var CURRY_FLAG = 8, PARTIAL_FLAG = 32, ARY_FLAG = 128, REARG_FLAG = 256; + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -30,7 +36,7 @@ define(['./LodashWrapper', './getData', './getFuncName', '../lang/isArray', './i throw new TypeError(FUNC_ERROR_TEXT); } if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { - wrapper = new LodashWrapper([]); + wrapper = new LodashWrapper([], true); } } index = wrapper ? -1 : length; @@ -38,7 +44,7 @@ define(['./LodashWrapper', './getData', './getFuncName', '../lang/isArray', './i func = funcs[index]; var funcName = getFuncName(func), - data = funcName == 'wrapper' ? getData(func) : null; + data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); @@ -47,12 +53,14 @@ define(['./LodashWrapper', './getData', './getFuncName', '../lang/isArray', './i } } return function() { - var args = arguments; - if (wrapper && args.length == 1 && isArray(args[0])) { - return wrapper.plant(args[0]).value(); + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); } var index = 0, - result = length ? funcs[index].apply(this, args) : args[0]; + result = length ? funcs[index].apply(this, args) : value; while (++index < length) { result = funcs[index].call(this, result); diff --git a/internal/createHybridWrapper.js b/internal/createHybridWrapper.js index 2a9767b50..1c7dabc73 100644 --- a/internal/createHybridWrapper.js +++ b/internal/createHybridWrapper.js @@ -40,7 +40,7 @@ define(['./arrayCopy', './composeArgs', './composeArgsRight', './createCtorWrapp isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, - Ctor = isBindKey ? null : createCtorWrapper(func); + Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -64,12 +64,12 @@ define(['./arrayCopy', './composeArgs', './composeArgsRight', './createCtorWrapp length -= argsHolders.length; if (length < arity) { - var newArgPos = argPos ? arrayCopy(argPos) : null, + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), - newsHolders = isCurry ? argsHolders : null, - newHoldersRight = isCurry ? null : argsHolders, - newPartials = isCurry ? args : null, - newPartialsRight = isCurry ? null : args; + newsHolders = isCurry ? argsHolders : undefined, + newHoldersRight = isCurry ? undefined : argsHolders, + newPartials = isCurry ? args : undefined, + newPartialsRight = isCurry ? undefined : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); diff --git a/internal/createPadding.js b/internal/createPadding.js index 4d0f12802..f0b0298eb 100644 --- a/internal/createPadding.js +++ b/internal/createPadding.js @@ -1,10 +1,8 @@ define(['../string/repeat', './root'], function(repeat, root) { - /** Native method references. */ - var ceil = Math.ceil; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsFinite = root.isFinite; + var nativeCeil = Math.ceil, + nativeIsFinite = root.isFinite; /** * Creates the padding required for `string` based on the given `length`. @@ -25,7 +23,7 @@ define(['../string/repeat', './root'], function(repeat, root) { } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); } return createPadding; diff --git a/internal/createPartial.js b/internal/createPartial.js index 05ee404e0..cf1bf8f0a 100644 --- a/internal/createPartial.js +++ b/internal/createPartial.js @@ -1,5 +1,8 @@ define(['./createWrapper', './replaceHolders', '../function/restParam'], function(createWrapper, replaceHolders, restParam) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates a `_.partial` or `_.partialRight` function. * @@ -10,7 +13,7 @@ define(['./createWrapper', './replaceHolders', '../function/restParam'], functio function createPartial(flag) { var partialFunc = restParam(function(func, partials) { var holders = replaceHolders(partials, partialFunc.placeholder); - return createWrapper(func, flag, null, partials, holders); + return createWrapper(func, flag, undefined, partials, holders); }); return partialFunc; } diff --git a/internal/createPartialWrapper.js b/internal/createPartialWrapper.js index 38c9dd11d..0d256ceee 100644 --- a/internal/createPartialWrapper.js +++ b/internal/createPartialWrapper.js @@ -26,7 +26,7 @@ define(['./createCtorWrapper', './root'], function(createCtorWrapper, root) { argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, - args = Array(argsLength + leftLength); + args = Array(leftLength + argsLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; diff --git a/internal/createRound.js b/internal/createRound.js new file mode 100644 index 000000000..2314c4102 --- /dev/null +++ b/internal/createRound.js @@ -0,0 +1,29 @@ +define([], function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Native method references. */ + var pow = Math.pow; + + /** + * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : (+precision || 0); + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + + return createRound; +}); diff --git a/internal/createWrapper.js b/internal/createWrapper.js index 4c2d0ea98..f4a8c2e3a 100644 --- a/internal/createWrapper.js +++ b/internal/createWrapper.js @@ -48,16 +48,16 @@ define(['./baseSetData', './createBindWrapper', './createHybridWrapper', './crea var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); - partials = holders = null; + partials = holders = undefined; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; - partials = holders = null; + partials = holders = undefined; } - var data = isBindKey ? null : getData(func), + var data = isBindKey ? undefined : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data) { diff --git a/internal/equalByTag.js b/internal/equalByTag.js index 8c01d1f16..a77428551 100644 --- a/internal/equalByTag.js +++ b/internal/equalByTag.js @@ -16,7 +16,7 @@ define([], function() { * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private - * @param {Object} value The object to compare. + * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. diff --git a/internal/escapeRegExpChar.js b/internal/escapeRegExpChar.js new file mode 100644 index 000000000..228f4d12e --- /dev/null +++ b/internal/escapeRegExpChar.js @@ -0,0 +1,41 @@ +define([], function() { + + /** Used to escape characters for inclusion in compiled regexes. */ + var regexpEscapes = { + '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', + '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', + 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', + 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', + 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** + * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes. + * + * @private + * @param {string} chr The matched character to escape. + * @param {string} leadingChar The capture group for a leading character. + * @param {string} whitespaceChar The capture group for a whitespace character. + * @returns {string} Returns the escaped character. + */ + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return '\\' + chr; + } + + return escapeRegExpChar; +}); diff --git a/internal/escapeStringChar.js b/internal/escapeStringChar.js index a51860e0e..93d4d6467 100644 --- a/internal/escapeStringChar.js +++ b/internal/escapeStringChar.js @@ -11,8 +11,7 @@ define([], function() { }; /** - * Used by `_.template` to escape characters for inclusion in compiled - * string literals. + * Used by `_.template` to escape characters for inclusion in compiled string literals. * * @private * @param {string} chr The matched character to escape. diff --git a/internal/getView.js b/internal/getView.js index 4d15b1127..7d0c74267 100644 --- a/internal/getView.js +++ b/internal/getView.js @@ -10,13 +10,13 @@ define([], function() { * @private * @param {number} start The start of the view. * @param {number} end The end of the view. - * @param {Array} [transforms] The transformations to apply to the view. + * @param {Array} transforms The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, - length = transforms ? transforms.length : 0; + length = transforms.length; while (++index < length) { var data = transforms[index], diff --git a/internal/isIndex.js b/internal/isIndex.js index ced084b82..1eb122013 100644 --- a/internal/isIndex.js +++ b/internal/isIndex.js @@ -4,7 +4,7 @@ define([], function() { var reIsUint = /^\d+$/; /** - * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; diff --git a/internal/isLength.js b/internal/isLength.js index f96fa0b73..7a8762c4f 100644 --- a/internal/isLength.js +++ b/internal/isLength.js @@ -1,7 +1,7 @@ define([], function() { /** - * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; @@ -9,7 +9,7 @@ define([], function() { /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @private * @param {*} value The value to check. diff --git a/internal/lazyClone.js b/internal/lazyClone.js index 0edbf1608..0179895ea 100644 --- a/internal/lazyClone.js +++ b/internal/lazyClone.js @@ -9,17 +9,13 @@ define(['./LazyWrapper', './arrayCopy'], function(LazyWrapper, arrayCopy) { * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { - var actions = this.__actions__, - iteratees = this.__iteratees__, - views = this.__views__, - result = new LazyWrapper(this.__wrapped__); - - result.__actions__ = actions ? arrayCopy(actions) : null; + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; - result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__iteratees__ = arrayCopy(this.__iteratees__); result.__takeCount__ = this.__takeCount__; - result.__views__ = views ? arrayCopy(views) : null; + result.__views__ = arrayCopy(this.__views__); return result; } diff --git a/internal/lazyValue.js b/internal/lazyValue.js index f10a4d664..c7a58d32d 100644 --- a/internal/lazyValue.js +++ b/internal/lazyValue.js @@ -1,8 +1,10 @@ define(['./baseWrapperValue', './getView', '../lang/isArray'], function(baseWrapperValue, getView, isArray) { + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** Used to indicate the type of lazy iteratees. */ - var LAZY_DROP_WHILE_FLAG = 0, - LAZY_FILTER_FLAG = 1, + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; /* Native method references for those with the same name as other `lodash` methods. */ @@ -17,22 +19,25 @@ define(['./baseWrapperValue', './getView', '../lang/isArray'], function(baseWrap * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.__wrapped__.value(); - if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__); - } - var dir = this.__dir__, + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), isRight = dir < 0, - view = getView(0, array.length, this.__views__), + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : (start - 1), - takeCount = nativeMin(length, this.__takeCount__), iteratees = this.__iteratees__, - iterLength = iteratees ? iteratees.length : 0, + iterLength = iteratees.length, resIndex = 0, - result = []; + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { + return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__); + } + var result = []; outer: while (length-- && resIndex < takeCount) { @@ -44,30 +49,16 @@ define(['./baseWrapperValue', './getView', '../lang/isArray'], function(baseWrap while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, - type = data.type; + type = data.type, + computed = iteratee(value); - if (type == LAZY_DROP_WHILE_FLAG) { - if (data.done && (isRight ? (index > data.index) : (index < data.index))) { - data.count = 0; - data.done = false; - } - data.index = index; - if (!data.done) { - var limit = data.limit; - if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) { - continue outer; - } - } - } else { - var computed = iteratee(value); - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; } } } diff --git a/internal/mergeDefaults.js b/internal/mergeDefaults.js new file mode 100644 index 000000000..77c9ba434 --- /dev/null +++ b/internal/mergeDefaults.js @@ -0,0 +1,19 @@ +define(['../object/merge'], function(merge) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + + return mergeDefaults; +}); diff --git a/internal/shimIsPlainObject.js b/internal/shimIsPlainObject.js deleted file mode 100644 index 21901b116..000000000 --- a/internal/shimIsPlainObject.js +++ /dev/null @@ -1,53 +0,0 @@ -define(['./baseForIn', './isObjectLike'], function(baseForIn, isObjectLike) { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; - - /** `Object#toString` result references. */ - var objectTag = '[object Object]'; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - - /** - * A fallback implementation of `_.isPlainObject` which checks if `value` - * is an object created by the `Object` constructor or has a `[[Prototype]]` - * of `null`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - */ - function shimIsPlainObject(value) { - var Ctor; - - // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag) || - (!hasOwnProperty.call(value, 'constructor') && - (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { - return false; - } - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - var result; - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - baseForIn(value, function(subValue, key) { - result = key; - }); - return result === undefined || hasOwnProperty.call(value, result); - } - - return shimIsPlainObject; -}); diff --git a/lang/isArguments.js b/lang/isArguments.js index 66a290a68..17d3c9cf1 100644 --- a/lang/isArguments.js +++ b/lang/isArguments.js @@ -1,16 +1,13 @@ define(['../internal/isArrayLike', '../internal/isObjectLike'], function(isArrayLike, isObjectLike) { - /** `Object#toString` result references. */ - var argsTag = '[object Arguments]'; - /** Used for native method references. */ var objectProto = Object.prototype; - /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Native method references. */ + var propertyIsEnumerable = objectProto.propertyIsEnumerable; /** * Checks if `value` is classified as an `arguments` object. @@ -29,7 +26,8 @@ define(['../internal/isArrayLike', '../internal/isObjectLike'], function(isArray * // => false */ function isArguments(value) { - return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag; + return isObjectLike(value) && isArrayLike(value) && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); } return isArguments; diff --git a/lang/isArray.js b/lang/isArray.js index d37ad32cd..075585188 100644 --- a/lang/isArray.js +++ b/lang/isArray.js @@ -7,7 +7,7 @@ define(['../internal/getNative', '../internal/isLength', '../internal/isObjectLi var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isBoolean.js b/lang/isBoolean.js index a40179c89..2545332f4 100644 --- a/lang/isBoolean.js +++ b/lang/isBoolean.js @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isDate.js b/lang/isDate.js index cffe36e17..fc8d78c6f 100644 --- a/lang/isDate.js +++ b/lang/isDate.js @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isElement.js b/lang/isElement.js index a0bf58349..780c44916 100644 --- a/lang/isElement.js +++ b/lang/isElement.js @@ -1,13 +1,4 @@ -define(['../internal/isObjectLike', './isPlainObject', '../support'], function(isObjectLike, isPlainObject, support) { - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; +define(['../internal/isObjectLike', './isPlainObject'], function(isObjectLike, isPlainObject) { /** * Checks if `value` is a DOM element. @@ -26,14 +17,7 @@ define(['../internal/isObjectLike', './isPlainObject', '../support'], function(i * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && - (objToString.call(value).indexOf('Element') > -1); - } - // Fallback for environments without DOM support. - if (!support.dom) { - isElement = function(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); - }; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } return isElement; diff --git a/lang/isError.js b/lang/isError.js index bfb28023e..484eb4c5c 100644 --- a/lang/isError.js +++ b/lang/isError.js @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isFinite.js b/lang/isFinite.js index f3701741d..bedd3d6ca 100644 --- a/lang/isFinite.js +++ b/lang/isFinite.js @@ -1,13 +1,12 @@ -define(['../internal/getNative', '../internal/root'], function(getNative, root) { +define(['../internal/root'], function(root) { /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsFinite = root.isFinite, - nativeNumIsFinite = getNative(Number, 'isFinite'); + var nativeIsFinite = root.isFinite; /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). + * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). * * @static * @memberOf _ @@ -31,9 +30,9 @@ define(['../internal/getNative', '../internal/root'], function(getNative, root) * _.isFinite(Infinity); * // => false */ - var isFinite = nativeNumIsFinite || function(value) { + function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); - }; + } return isFinite; }); diff --git a/lang/isFunction.js b/lang/isFunction.js index 3e6b4cfbc..8672a89b1 100644 --- a/lang/isFunction.js +++ b/lang/isFunction.js @@ -1,4 +1,4 @@ -define(['../internal/baseIsFunction', '../internal/getNative', '../internal/root'], function(baseIsFunction, getNative, root) { +define(['./isObject'], function(isObject) { /** `Object#toString` result references. */ var funcTag = '[object Function]'; @@ -7,14 +7,11 @@ define(['../internal/baseIsFunction', '../internal/getNative', '../internal/root var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; - /** Native method references. */ - var Uint8Array = getNative(root, 'Uint8Array'); - /** * Checks if `value` is classified as a `Function` object. * @@ -31,12 +28,12 @@ define(['../internal/baseIsFunction', '../internal/getNative', '../internal/root * _.isFunction(/abc/); * // => false */ - var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { + function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. - return objToString.call(value) == funcTag; - }; + return isObject(value) && objToString.call(value) == funcTag; + } return isFunction; }); diff --git a/lang/isNative.js b/lang/isNative.js index bbd7601b9..662fd2139 100644 --- a/lang/isNative.js +++ b/lang/isNative.js @@ -1,7 +1,4 @@ -define(['../string/escapeRegExp', '../internal/isObjectLike'], function(escapeRegExp, isObjectLike) { - - /** `Object#toString` result references. */ - var funcTag = '[object Function]'; +define(['./isFunction', '../internal/isObjectLike'], function(isFunction, isObjectLike) { /** Used to detect host constructors (Safari > 5). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; @@ -15,15 +12,9 @@ define(['../string/escapeRegExp', '../internal/isObjectLike'], function(escapeRe /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; - /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(fnToString.call(hasOwnProperty)) + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); @@ -47,7 +38,7 @@ define(['../string/escapeRegExp', '../internal/isObjectLike'], function(escapeRe if (value == null) { return false; } - if (objToString.call(value) == funcTag) { + if (isFunction(value)) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && reIsHostCtor.test(value); diff --git a/lang/isNumber.js b/lang/isNumber.js index 68aed9b02..3a97326dd 100644 --- a/lang/isNumber.js +++ b/lang/isNumber.js @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isPlainObject.js b/lang/isPlainObject.js index 70a9f80cf..cd3b829e7 100644 --- a/lang/isPlainObject.js +++ b/lang/isPlainObject.js @@ -1,4 +1,7 @@ -define(['../internal/getNative', '../internal/shimIsPlainObject'], function(getNative, shimIsPlainObject) { +define(['../internal/baseForIn', './isArguments', '../internal/isObjectLike'], function(baseForIn, isArguments, isObjectLike) { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; /** `Object#toString` result references. */ var objectTag = '[object Object]'; @@ -6,15 +9,15 @@ define(['../internal/getNative', '../internal/shimIsPlainObject'], function(getN /** Used for native method references. */ var objectProto = Object.prototype; + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; - /** Native method references. */ - var getPrototypeOf = getNative(Object, 'getPrototypeOf'); - /** * Checks if `value` is a plain object, that is, an object created by the * `Object` constructor or one with a `[[Prototype]]` of `null`. @@ -45,17 +48,26 @@ define(['../internal/getNative', '../internal/shimIsPlainObject'], function(getN * _.isPlainObject(Object.create(null)); * // => true */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && objToString.call(value) == objectTag)) { + function isPlainObject(value) { + var Ctor; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } - var valueOf = getNative(value, 'valueOf'), - objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } return isPlainObject; }); diff --git a/lang/isRegExp.js b/lang/isRegExp.js index ea56e70c1..f600e646d 100644 --- a/lang/isRegExp.js +++ b/lang/isRegExp.js @@ -1,4 +1,4 @@ -define(['../internal/isObjectLike'], function(isObjectLike) { +define(['./isObject'], function(isObject) { /** `Object#toString` result references. */ var regexpTag = '[object RegExp]'; @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; @@ -29,7 +29,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { * // => false */ function isRegExp(value) { - return isObjectLike(value) && objToString.call(value) == regexpTag; + return isObject(value) && objToString.call(value) == regexpTag; } return isRegExp; diff --git a/lang/isString.js b/lang/isString.js index 3538ad9f5..7bee4b1a0 100644 --- a/lang/isString.js +++ b/lang/isString.js @@ -7,7 +7,7 @@ define(['../internal/isObjectLike'], function(isObjectLike) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/lang/isTypedArray.js b/lang/isTypedArray.js index 91f177682..bafddfbde 100644 --- a/lang/isTypedArray.js +++ b/lang/isTypedArray.js @@ -45,7 +45,7 @@ define(['../internal/isLength', '../internal/isObjectLike'], function(isLength, var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; diff --git a/main.js b/main.js index 84ca1b510..f73622c55 100644 --- a/main.js +++ b/main.js @@ -1,6 +1,6 @@ /** * @license - * lodash 3.9.3 (Custom Build) + * lodash 3.10.0 (Custom Build) * Build: `lodash modern exports="amd" -d -o ./main.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.3 @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '3.9.3'; + var VERSION = '3.10.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -34,9 +34,11 @@ var HOT_COUNT = 150, HOT_SPAN = 16; + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + /** Used to indicate the type of lazy iteratees. */ - var LAZY_DROP_WHILE_FLAG = 0, - LAZY_FILTER_FLAG = 1, + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; /** Used as the `TypeError` message for "Functions" methods. */ @@ -93,11 +95,10 @@ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; /** - * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). - * In addition to special characters the forward slash is escaped to allow for - * easier `eval` use and `Function` compilation. + * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) + * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ @@ -106,7 +107,7 @@ /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; - /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ + /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ @@ -138,25 +139,13 @@ return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); }()); - /** Used to detect and test for whitespace. */ - var whitespace = ( - // Basic whitespace characters. - ' \t\x0b\f\xa0\ufeff' + - - // Line terminators. - '\n\r\u2028\u2029' + - - // Unicode category "Zs" space separators. - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); - /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', - 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', - 'isFinite', 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'window' + 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite', + 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap' ]; /** Used to make template sourceURLs easier to identify. */ @@ -192,13 +181,6 @@ cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; - /** Used as an internal `_.debounce` options object by `_.throttle`. */ - var debounceOptions = { - 'leading': false, - 'maxWait': 0, - 'trailing': false - }; - /** Used to map latin-1 supplementary letters to basic latin letters. */ var deburredLetters = { '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', @@ -246,6 +228,15 @@ 'object': true }; + /** Used to escape characters for inclusion in compiled regexes. */ + var regexpEscapes = { + '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', + '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', + 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', + 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', + 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' + }; + /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', @@ -383,9 +374,6 @@ * @returns {string} Returns the string. */ function baseToString(value) { - if (typeof value == 'string') { - return value; - } return value == null ? '' : (value + ''); } @@ -427,8 +415,8 @@ * sort them in ascending order. * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { @@ -436,16 +424,16 @@ } /** - * Used by `_.sortByOrder` to compare multiple properties of each element - * in a collection and stable sort them in the following order: + * Used by `_.sortByOrder` to compare multiple properties of a value to another + * and stable sort them. * - * If `orders` is unspecified, sort in ascending order for all properties. - * Otherwise, for each property, sort in ascending order if its corresponding value in - * orders is true, and descending order if false. + * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise, + * a value is sorted in ascending order if its corresponding order is "asc", and + * descending if "desc". * * @private - * @param {Object} object The object to compare to `other`. - * @param {Object} other The object to compare to `object`. + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. * @param {boolean[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ @@ -462,7 +450,8 @@ if (index >= ordersLength) { return result; } - return result * (orders[index] ? 1 : -1); + var order = orders[index]; + return result * ((order === 'asc' || order === true) ? 1 : -1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications @@ -498,8 +487,25 @@ } /** - * Used by `_.template` to escape characters for inclusion in compiled - * string literals. + * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes. + * + * @private + * @param {string} chr The matched character to escape. + * @param {string} leadingChar The capture group for a leading character. + * @param {string} whitespaceChar The capture group for a whitespace character. + * @returns {string} Returns the escaped character. + */ + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return '\\' + chr; + } + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. * * @private * @param {string} chr The matched character to escape. @@ -710,9 +716,6 @@ objectProto = Object.prototype, stringProto = String.prototype; - /** Used to detect DOM support. */ - var document = (document = context.window) ? document.document : null; - /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; @@ -723,56 +726,42 @@ var idCounter = 0; /** - * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; /** Used to restore the original `_` reference in `_.noConflict`. */ - var oldDash = context._; + var oldDash = root._; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(fnToString.call(hasOwnProperty)) + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references. */ - var ArrayBuffer = getNative(context, 'ArrayBuffer'), - bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), - ceil = Math.ceil, + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, - floor = Math.floor, - getPrototypeOf = getNative(Object, 'getPrototypeOf'), parseFloat = context.parseFloat, - push = arrayProto.push, + pow = Math.pow, + propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, 'Set'), setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = getNative(context, 'Uint8Array'), + Uint8Array = context.Uint8Array, WeakMap = getNative(context, 'WeakMap'); - /** Used to clone array buffers. */ - var Float64Array = (function() { - // Safari 5 errors when using an array buffer to initialize a typed array - // where the array buffer's `byteLength` is not a multiple of the typed - // array's `BYTES_PER_ELEMENT`. - try { - var func = getNative(context, 'Float64Array'), - result = new func(new ArrayBuffer(10), 0, 1) && func; - } catch(e) {} - return result || null; - }()); - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeCreate = getNative(Object, 'create'), + var nativeCeil = Math.ceil, + nativeCreate = getNative(Object, 'create'), + nativeFloor = Math.floor, nativeIsArray = getNative(Array, 'isArray'), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, 'now'), - nativeNumIsFinite = getNative(Number, 'isFinite'), nativeParseInt = context.parseInt, nativeRandom = Math.random; @@ -785,11 +774,8 @@ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - /** Used as the size, in bytes, of each `Float64Array` element. */ - var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; - /** - * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; @@ -805,15 +791,16 @@ /** * Creates a `lodash` object which wraps `value` to enable implicit chaining. * Methods that operate on and return arrays, collections, and functions can - * be chained together. Methods that return a boolean or single value will - * automatically end the chain returning the unwrapped value. Explicit chaining - * may be enabled using `_.chain`. The execution of chained methods is lazy, - * that is, execution is deferred until `_#value` is implicitly or explicitly - * called. + * be chained together. Methods that retrieve a single value or may return a + * primitive value will automatically end the chain returning the unwrapped + * value. Explicit chaining may be enabled using `_.chain`. The execution of + * chained methods is lazy, that is, execution is deferred until `_#value` + * is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization that merges iteratees to avoid creating intermediate - * arrays and reduce the number of iteratee executions. + * fusion is an optimization strategy which merge iteratee calls; this can help + * to avoid the creation of intermediate data structures and greatly reduce the + * number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. @@ -836,36 +823,37 @@ * The chainable wrapper methods are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, - * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, - * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, - * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, - * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, - * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, - * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, - * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, - * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, - * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, - * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, - * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, - * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, + * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, + * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, + * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, + * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, + * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, + * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, - * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, - * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, - * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, - * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, - * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, - * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, - * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, - * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, - * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, - * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, - * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, + * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, + * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, + * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, + * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, + * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, + * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, + * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, + * `unescape`, `uniqueId`, `value`, and `words` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. @@ -940,27 +928,6 @@ */ var support = lodash.support = {}; - (function(x) { - var Ctor = function() { this.x = x; }, - object = { '0': x, 'length': x }, - props = []; - - Ctor.prototype = { 'valueOf': x, 'y': x }; - for (var key in new Ctor) { props.push(key); } - - /** - * Detect if the DOM is supported. - * - * @memberOf _.support - * @type boolean - */ - try { - support.dom = document.createDocumentFragment().nodeType === 11; - } catch(e) { - support.dom = false; - } - }(1, 0)); - /** * By default, the template delimiters used by lodash are like those in * embedded Ruby (ERB). Change the following template settings to use @@ -1032,13 +999,12 @@ */ function LazyWrapper(value) { this.__wrapped__ = value; - this.__actions__ = null; + this.__actions__ = []; this.__dir__ = 1; - this.__dropCount__ = 0; this.__filtered__ = false; - this.__iteratees__ = null; + this.__iteratees__ = []; this.__takeCount__ = POSITIVE_INFINITY; - this.__views__ = null; + this.__views__ = []; } /** @@ -1050,17 +1016,13 @@ * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { - var actions = this.__actions__, - iteratees = this.__iteratees__, - views = this.__views__, - result = new LazyWrapper(this.__wrapped__); - - result.__actions__ = actions ? arrayCopy(actions) : null; + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; - result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__iteratees__ = arrayCopy(this.__iteratees__); result.__takeCount__ = this.__takeCount__; - result.__views__ = views ? arrayCopy(views) : null; + result.__views__ = arrayCopy(this.__views__); return result; } @@ -1093,22 +1055,25 @@ * @returns {*} Returns the unwrapped value. */ function lazyValue() { - var array = this.__wrapped__.value(); - if (!isArray(array)) { - return baseWrapperValue(array, this.__actions__); - } - var dir = this.__dir__, + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), isRight = dir < 0, - view = getView(0, array.length, this.__views__), + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : (start - 1), - takeCount = nativeMin(length, this.__takeCount__), iteratees = this.__iteratees__, - iterLength = iteratees ? iteratees.length : 0, + iterLength = iteratees.length, resIndex = 0, - result = []; + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { + return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__); + } + var result = []; outer: while (length-- && resIndex < takeCount) { @@ -1120,30 +1085,16 @@ while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, - type = data.type; + type = data.type, + computed = iteratee(value); - if (type == LAZY_DROP_WHILE_FLAG) { - if (data.done && (isRight ? (index > data.index) : (index < data.index))) { - data.count = 0; - data.done = false; - } - data.index = index; - if (!data.done) { - var limit = data.limit; - if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) { - continue outer; - } - } - } else { - var computed = iteratee(value); - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; } } } @@ -1275,6 +1226,30 @@ /*------------------------------------------------------------------------*/ + /** + * Creates a new array joining `array` with `other`. + * + * @private + * @param {Array} array The array to join. + * @param {Array} other The other array to join. + * @returns {Array} Returns the new concatenated array. + */ + function arrayConcat(array, other) { + var index = -1, + length = array.length, + othIndex = -1, + othLength = other.length, + result = Array(length + othLength); + + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + /** * Copies the values of `source` to `array`. * @@ -1430,6 +1405,25 @@ return result; } + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands and `this` binding. @@ -1501,18 +1495,20 @@ } /** - * A specialized version of `_.sum` for arrays without support for iteratees. + * A specialized version of `_.sum` for arrays without support for callback + * shorthands and `this` binding.. * * @private * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the sum. */ - function arraySum(array) { + function arraySum(array, iteratee) { var length = array.length, result = 0; while (length--) { - result += +array[length] || 0; + result += +iteratee(array[length]) || 0; } return result; } @@ -1716,7 +1712,7 @@ : (object ? value : {}); } } - // Check for circular references and return corresponding clone. + // Check for circular references and return its corresponding clone. stackA || (stackA = []); stackB || (stackB = []); @@ -1751,7 +1747,7 @@ if (isObject(prototype)) { object.prototype = prototype; var result = new object; - object.prototype = null; + object.prototype = undefined; } return result || {}; }; @@ -1793,7 +1789,7 @@ var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, - cache = (isCommon && values.length >= 200) ? createCache(values) : null, + cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, valuesLength = values.length; if (cache) { @@ -1969,13 +1965,14 @@ * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isDeep, isStrict) { + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, - length = array.length, - resIndex = -1, - result = []; + length = array.length; while (++index < length) { var value = array[index]; @@ -1983,16 +1980,12 @@ (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict); - } - var valIndex = -1, - valLength = value.length; - - while (++valIndex < valLength) { - result[++resIndex] = value[valIndex]; + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); } } else if (!isStrict) { - result[++resIndex] = value; + result[result.length] = value; } } return result; @@ -2347,7 +2340,7 @@ * @private * @param {Object} object The destination object. * @param {Object} source The source object. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns `object`. @@ -2357,7 +2350,7 @@ return object; } var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), - props = isSrcArr ? null : keys(source); + props = isSrcArr ? undefined : keys(source); arrayEach(props || source, function(srcValue, key) { if (props) { @@ -2396,7 +2389,7 @@ * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize merging properties. + * @param {Function} [customizer] The function to customize merged values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. @@ -2503,7 +2496,7 @@ * @returns {number} Returns the random number. */ function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + return min + nativeFloor(nativeRandom() * (max - min + 1)); } /** @@ -2669,7 +2662,7 @@ indexOf = getIndexOf(), length = array.length, isCommon = indexOf == baseIndexOf, - isLarge = isCommon && length >= 200, + isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; @@ -2768,11 +2761,8 @@ length = actions.length; while (++index < length) { - var args = [result], - action = actions[index]; - - push.apply(args, action.args); - result = action.func.apply(action.thisArg, args); + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([result], action.args)); } return result; } @@ -2831,7 +2821,7 @@ valIsUndef = value === undefined; while (low < high) { - var mid = floor((low + high) / 2), + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; @@ -2900,26 +2890,11 @@ * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { - return bufferSlice.call(buffer, 0); - } - if (!bufferSlice) { - // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. - bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { - var byteLength = buffer.byteLength, - floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, - offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, - result = new ArrayBuffer(byteLength); + var result = new ArrayBuffer(buffer.byteLength), + view = new Uint8Array(result); - if (floatLength) { - var view = new Float64Array(result, 0, floatLength); - view.set(new Float64Array(buffer, 0, floatLength)); - } - if (byteLength != offset) { - view = new Uint8Array(result, offset); - view.set(new Uint8Array(buffer, offset)); - } - return result; - }; + view.set(new Uint8Array(buffer)); + return result; } /** @@ -2938,7 +2913,7 @@ argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, - result = Array(argsLength + leftLength); + result = Array(leftLength + argsLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; @@ -2985,12 +2960,7 @@ } /** - * Creates a function that aggregates a collection, creating an accumulator - * object composed from the results of running each element in the collection - * through an iteratee. - * - * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, - * and `_.partition`. + * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. @@ -3020,10 +2990,7 @@ } /** - * Creates a function that assigns properties of source object(s) to a given - * destination object. - * - * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * Creates a `_.assign`, `_.defaults`, or `_.merge` function. * * @private * @param {Function} assigner The function to assign values. @@ -3134,9 +3101,9 @@ * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ - var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { - return new SetCache(values); - }; + function createCache(values) { + return (nativeCreate && Set) ? new SetCache(values) : null; + } /** * Creates a function that produces compound words out of the words in a @@ -3171,7 +3138,7 @@ function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. - // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -3181,6 +3148,8 @@ case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); @@ -3201,15 +3170,34 @@ function createCurry(flag) { function curryFunc(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { - arity = null; + arity = undefined; } - var result = createWrapper(func, flag, null, null, null, null, null, arity); + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryFunc.placeholder; return result; } return curryFunc; } + /** + * Creates a `_.defaults` or `_.defaultsDeep` function. + * + * @private + * @param {Function} assigner The function to assign values. + * @param {Function} customizer The function to customize assigned values. + * @returns {Function} Returns the new defaults function. + */ + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + /** * Creates a `_.max` or `_.min` function. * @@ -3221,11 +3209,11 @@ function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } iteratee = getCallback(iteratee, thisArg, 3); if (iteratee.length == 1) { - collection = toIterable(collection); + collection = isArray(collection) ? collection : toIterable(collection); var result = arrayExtremum(collection, iteratee, comparator, exValue); if (!(collection.length && result === exValue)) { return result; @@ -3306,7 +3294,7 @@ throw new TypeError(FUNC_ERROR_TEXT); } if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { - wrapper = new LodashWrapper([]); + wrapper = new LodashWrapper([], true); } } index = wrapper ? -1 : length; @@ -3314,7 +3302,7 @@ func = funcs[index]; var funcName = getFuncName(func), - data = funcName == 'wrapper' ? getData(func) : null; + data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); @@ -3323,12 +3311,14 @@ } } return function() { - var args = arguments; - if (wrapper && args.length == 1 && isArray(args[0])) { - return wrapper.plant(args[0]).value(); + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); } var index = 0, - result = length ? funcs[index].apply(this, args) : args[0]; + result = length ? funcs[index].apply(this, args) : value; while (++index < length) { result = funcs[index].call(this, result); @@ -3432,7 +3422,7 @@ function createPartial(flag) { var partialFunc = restParam(function(func, partials) { var holders = replaceHolders(partials, partialFunc.placeholder); - return createWrapper(func, flag, null, partials, holders); + return createWrapper(func, flag, undefined, partials, holders); }); return partialFunc; } @@ -3478,7 +3468,7 @@ isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, - Ctor = isBindKey ? null : createCtorWrapper(func); + Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -3502,12 +3492,12 @@ length -= argsHolders.length; if (length < arity) { - var newArgPos = argPos ? arrayCopy(argPos) : null, + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), - newsHolders = isCurry ? argsHolders : null, - newHoldersRight = isCurry ? null : argsHolders, - newPartials = isCurry ? args : null, - newPartialsRight = isCurry ? null : args; + newsHolders = isCurry ? argsHolders : undefined, + newHoldersRight = isCurry ? undefined : argsHolders, + newPartials = isCurry ? args : undefined, + newPartialsRight = isCurry ? undefined : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); @@ -3561,7 +3551,7 @@ } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); } /** @@ -3587,7 +3577,7 @@ argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, - args = Array(argsLength + leftLength); + args = Array(leftLength + argsLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; @@ -3601,6 +3591,25 @@ return wrapper; } + /** + * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : (+precision || 0); + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + /** * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. * @@ -3650,16 +3659,16 @@ var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); - partials = holders = null; + partials = holders = undefined; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; - partials = holders = null; + partials = holders = undefined; } - var data = isBindKey ? null : getData(func), + var data = isBindKey ? undefined : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data) { @@ -3738,7 +3747,7 @@ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private - * @param {Object} value The object to compare. + * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. @@ -3938,13 +3947,13 @@ * @private * @param {number} start The start of the view. * @param {number} end The end of the view. - * @param {Array} [transforms] The transformations to apply to the view. + * @param {Array} transforms The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, - length = transforms ? transforms.length : 0; + length = transforms.length; while (++index < length) { var data = transforms[index], @@ -4143,7 +4152,7 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @private * @param {*} value The value to check. @@ -4235,6 +4244,18 @@ return data; } + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. + */ + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + /** * A specialized version of `_.pick` which picks `object` properties specified * by `props`. @@ -4334,38 +4355,6 @@ }; }()); - /** - * A fallback implementation of `_.isPlainObject` which checks if `value` - * is an object created by the `Object` constructor or has a `[[Prototype]]` - * of `null`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - */ - function shimIsPlainObject(value) { - var Ctor, - support = lodash.support; - - // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag) || - (!hasOwnProperty.call(value, 'constructor') && - (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { - return false; - } - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - var result; - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - baseForIn(value, function(subValue, key) { - result = key; - }); - return result === undefined || hasOwnProperty.call(value, result); - } - /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. @@ -4479,12 +4468,12 @@ if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { - size = nativeMax(+size || 1, 1); + size = nativeMax(nativeFloor(size) || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, - result = Array(ceil(length / size)); + result = Array(nativeCeil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); @@ -4523,7 +4512,7 @@ /** * Creates an array of unique `array` values not included in the other - * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -4538,7 +4527,7 @@ * // => [1, 3] */ var difference = restParam(function(array, values) { - return isArrayLike(array) + return (isObjectLike(array) && isArrayLike(array)) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); @@ -4933,7 +4922,7 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` * performs a faster binary search. @@ -4967,10 +4956,9 @@ if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; } else if (fromIndex) { - var index = binaryIndex(array, value), - other = array[index]; - - if (value === value ? (value === other) : (other !== other)) { + var index = binaryIndex(array, value); + if (index < length && + (value === value ? (value === array[index]) : (array[index] !== array[index]))) { return index; } return -1; @@ -4997,7 +4985,7 @@ /** * Creates an array of unique values that are included in all of the provided - * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5118,7 +5106,7 @@ /** * Removes all provided values from `array` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. @@ -5551,7 +5539,7 @@ /** * Creates an array of unique values, in order, from all of the provided arrays - * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5570,7 +5558,7 @@ /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurence of each element * is kept. Providing `true` for `isSorted` performs a faster search algorithm * for sorted arrays. If an iteratee function is provided it is invoked for @@ -5624,7 +5612,7 @@ } if (isSorted != null && typeof isSorted != 'boolean') { thisArg = iteratee; - iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; isSorted = false; } var callback = getCallback(); @@ -5711,7 +5699,7 @@ /** * Creates an array excluding all provided values using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -5753,7 +5741,7 @@ var array = arguments[index]; if (isArrayLike(array)) { var result = result - ? baseDifference(result, array).concat(baseDifference(array, result)) + ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; } } @@ -5975,16 +5963,16 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).push(3); + * var wrapped = _(array).push(3); * * console.log(array); * // => [1, 2] * - * wrapper = wrapper.commit(); + * wrapped = wrapped.commit(); * console.log(array); * // => [1, 2, 3] * - * wrapper.last(); + * wrapped.last(); * // => 3 * * console.log(array); @@ -5994,6 +5982,33 @@ return new LodashWrapper(this.value(), this.__chain__); } + /** + * Creates a new array joining a wrapped array with any additional arrays + * and/or values. + * + * @name concat + * @memberOf _ + * @category Chain + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var wrapped = _(array).concat(2, [3], [[4]]); + * + * console.log(wrapped.value()); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [toObject(array)], values); + }); + }); + /** * Creates a clone of the chained sequence planting `value` as the wrapped value. * @@ -6004,17 +6019,17 @@ * @example * * var array = [1, 2]; - * var wrapper = _(array).map(function(value) { + * var wrapped = _(array).map(function(value) { * return Math.pow(value, 2); * }); * * var other = [3, 4]; - * var otherWrapper = wrapper.plant(other); + * var otherWrapped = wrapped.plant(other); * - * otherWrapper.value(); + * otherWrapped.value(); * // => [9, 16] * - * wrapper.value(); + * wrapped.value(); * // => [1, 4] */ function wrapperPlant(value) { @@ -6057,15 +6072,20 @@ */ function wrapperReverse() { var value = this.__wrapped__; + + var interceptor = function(value) { + return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse(); + }; if (value instanceof LazyWrapper) { + var wrapped = value; if (this.__actions__.length) { - value = new LazyWrapper(this); + wrapped = new LazyWrapper(this); } - return new LodashWrapper(value.reverse(), this.__chain__); + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(wrapped, this.__chain__); } - return this.thru(function(value) { - return value.reverse(); - }); + return this.thru(interceptor); } /** @@ -6223,7 +6243,7 @@ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -6497,7 +6517,7 @@ /** * Checks if `value` is in `collection` using - * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `collection`. * @@ -6530,17 +6550,14 @@ collection = values(collection); length = collection.length; } - if (!length) { - return false; - } if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; } else { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) - ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) - : (getIndexOf(collection, target, fromIndex) > -1); + ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) + : (!!length && getIndexOf(collection, target, fromIndex) > -1); } /** @@ -6622,7 +6639,7 @@ result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; @@ -6792,7 +6809,8 @@ * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, + * and `sortByOrder` * * @static * @memberOf _ @@ -7022,7 +7040,7 @@ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = null; + predicate = undefined; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); @@ -7083,7 +7101,7 @@ return []; } if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } var index = -1; iteratee = getCallback(iteratee, thisArg, 3); @@ -7142,9 +7160,9 @@ /** * This method is like `_.sortByAll` except that it allows specifying the - * sort orders of the iteratees to sort by. A truthy value in `orders` will - * sort the corresponding property name in ascending order while a falsey - * value will sort it in descending order. + * sort orders of the iteratees to sort by. If `orders` is unspecified, all + * values are sorted in ascending order. Otherwise, a value is sorted in + * ascending order if its corresponding order is "asc", and descending if "desc". * * If a property name is provided for an iteratee the created `_.property` * style callback returns the property value of the given element. @@ -7158,7 +7176,7 @@ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} orders The sort orders of `iteratees`. + * @param {boolean[]} [orders] The sort orders of `iteratees`. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example @@ -7171,7 +7189,7 @@ * ]; * * // sort by `user` in ascending order and by `age` in descending order - * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values); + * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] */ function sortByOrder(collection, iteratees, orders, guard) { @@ -7179,7 +7197,7 @@ return []; } if (guard && isIterateeCall(iteratees, orders, guard)) { - orders = null; + orders = undefined; } if (!isArray(iteratees)) { iteratees = iteratees == null ? [] : [iteratees]; @@ -7304,10 +7322,10 @@ */ function ary(func, n, guard) { if (guard && isIterateeCall(func, n, guard)) { - n = null; + n = undefined; } n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); - return createWrapper(func, ARY_FLAG, null, null, null, null, n); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } /** @@ -7342,7 +7360,7 @@ result = func.apply(this, arguments); } if (n <= 1) { - func = null; + func = undefined; } return result; }; @@ -7650,9 +7668,9 @@ var leading = true; trailing = false; } else if (isObject(options)) { - leading = options.leading; + leading = !!options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); - trailing = 'trailing' in options ? options.trailing : trailing; + trailing = 'trailing' in options ? !!options.trailing : trailing; } function cancel() { @@ -7662,41 +7680,35 @@ if (maxTimeoutId) { clearTimeout(maxTimeoutId); } + lastCalled = 0; maxTimeoutId = timeoutId = trailingCall = undefined; } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { - if (maxTimeoutId) { - clearTimeout(maxTimeoutId); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if (isCalled) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailingCall, maxTimeoutId); } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { - if (timeoutId) { - clearTimeout(timeoutId); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if (trailing || (maxWait !== wait)) { - lastCalled = now(); - result = func.apply(thisArg, args); - if (!timeoutId && !maxTimeoutId) { - args = thisArg = null; - } - } + complete(trailing, timeoutId); } function debounced() { @@ -7736,7 +7748,7 @@ result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { - args = thisArg = null; + args = thisArg = undefined; } return result; } @@ -7841,7 +7853,7 @@ * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) * method interface of `get`, `has`, and `set`. * * @static @@ -7902,6 +7914,52 @@ return memoized; } + /** + * Creates a function that runs each argument through a corresponding + * transform function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms] The functions to transform + * arguments, specified as individual functions or arrays of functions. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var modded = _.modArgs(function(x, y) { + * return [x, y]; + * }, square, doubled); + * + * modded(1, 2); + * // => [1, 4] + * + * modded(5, 10); + * // => [25, 20] + */ + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the @@ -8047,7 +8105,7 @@ * // => [3, 6, 9] */ var rearg = restParam(function(func, indexes) { - return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); }); /** @@ -8193,10 +8251,7 @@ leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } - debounceOptions.leading = leading; - debounceOptions.maxWait = +wait; - debounceOptions.trailing = trailing; - return debounce(func, wait, debounceOptions); + return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); } /** @@ -8222,7 +8277,7 @@ */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; - return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []); } /*------------------------------------------------------------------------*/ @@ -8408,7 +8463,8 @@ * // => false */ function isArguments(value) { - return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag; + return isObjectLike(value) && isArrayLike(value) && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); } /** @@ -8488,14 +8544,7 @@ * // => false */ function isElement(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && - (objToString.call(value).indexOf('Element') > -1); - } - // Fallback for environments without DOM support. - if (!support.dom) { - isElement = function(value) { - return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); - }; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } /** @@ -8610,7 +8659,7 @@ /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). + * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). * * @static * @memberOf _ @@ -8634,9 +8683,9 @@ * _.isFinite(Infinity); * // => false */ - var isFinite = nativeNumIsFinite || function(value) { + function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); - }; + } /** * Checks if `value` is classified as a `Function` object. @@ -8654,12 +8703,12 @@ * _.isFunction(/abc/); * // => false */ - var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { + function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. - return objToString.call(value) == funcTag; - }; + return isObject(value) && objToString.call(value) == funcTag; + } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. @@ -8783,7 +8832,7 @@ if (value == null) { return false; } - if (objToString.call(value) == funcTag) { + if (isFunction(value)) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && reIsHostCtor.test(value); @@ -8865,17 +8914,26 @@ * _.isPlainObject(Object.create(null)); * // => true */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && objToString.call(value) == objectTag)) { + function isPlainObject(value) { + var Ctor; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } - var valueOf = getNative(value, 'valueOf'), - objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } /** * Checks if `value` is classified as a `RegExp` object. @@ -8894,7 +8952,7 @@ * // => false */ function isRegExp(value) { - return isObjectLike(value) && objToString.call(value) == regexpTag; + return isObject(value) && objToString.call(value) == regexpTag; } /** @@ -9060,6 +9118,56 @@ /*------------------------------------------------------------------------*/ + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * overwrite property assignments of previous sources. If `customizer` is + * provided it 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 bound to `thisArg` and invoked + * with five arguments: (objectValue, sourceValue, key, object, source). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. + * @example + * + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; + * + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; + * + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } + * + * // using a customizer callback + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(object, other, function(a, b) { + * if (_.isArray(a)) { + * return a.concat(b); + * } + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } + */ + var merge = createAssigner(baseMerge); + /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. @@ -9068,7 +9176,7 @@ * (objectValue, sourceValue, key, object, source). * * **Note:** This method mutates `object` and is based on - * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). + * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). * * @static * @memberOf _ @@ -9135,7 +9243,7 @@ function create(prototype, properties, guard) { var result = baseCreate(prototype); if (guard && isIterateeCall(prototype, properties, guard)) { - properties = null; + properties = undefined; } return properties ? baseAssign(result, properties) : result; } @@ -9158,14 +9266,27 @@ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ - var defaults = restParam(function(args) { - var object = args[0]; - if (object == null) { - return object; - } - args.push(assignDefaults); - return assign.apply(undefined, args); - }); + var defaults = createDefaults(assign, assignDefaults); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); + * // => { 'user': { 'name': 'barney', 'age': 36 } } + * + */ + var defaultsDeep = createDefaults(merge, mergeDefaults); /** * This method is like `_.find` except that it returns the key of the first @@ -9492,7 +9613,7 @@ */ function invert(object, multiValue, guard) { if (guard && isIterateeCall(object, multiValue, guard)) { - multiValue = null; + multiValue = undefined; } var index = -1, props = keys(object), @@ -9521,7 +9642,7 @@ * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static @@ -9545,7 +9666,7 @@ * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object == null ? null : object.constructor; + var Ctor = object == null ? undefined : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); @@ -9669,56 +9790,6 @@ */ var mapValues = createObjectMapper(); - /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * overwrite property assignments of previous sources. If `customizer` is - * provided it 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 bound to `thisArg` and invoked - * with five arguments: (objectValue, sourceValue, key, object, source). - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {Object} Returns `object`. - * @example - * - * var users = { - * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] - * }; - * - * var ages = { - * 'data': [{ 'age': 36 }, { 'age': 40 }] - * }; - * - * _.merge(users, ages); - * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } - * - * // using a customizer callback - * var object = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var other = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(object, other, function(a, b) { - * if (_.isArray(a)) { - * return a.concat(b); - * } - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } - */ - var merge = createAssigner(baseMerge); - /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable properties of `object` that are not omitted. @@ -9949,7 +10020,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } } else { accumulator = {}; @@ -10052,7 +10123,7 @@ */ function inRange(value, start, end) { start = +start || 0; - if (typeof end === 'undefined') { + if (end === undefined) { end = start; start = 0; } else { @@ -10090,7 +10161,7 @@ */ function random(min, max, floating) { if (floating && isIterateeCall(min, max, floating)) { - max = floating = null; + max = floating = undefined; } var noMin = min == null, noMax = max == null; @@ -10277,8 +10348,8 @@ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, '\\$&') - : string; + ? string.replace(reRegExpChars, escapeRegExpChar) + : (string || '(?:)'); } /** @@ -10335,8 +10406,8 @@ return string; } var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); + leftLength = nativeFloor(mid), + rightLength = nativeCeil(mid); chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; @@ -10414,25 +10485,16 @@ * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - if (guard && isIterateeCall(string, radix, guard)) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { radix = 0; + } else if (radix) { + radix = +radix; } - return nativeParseInt(string, radix); - } - // Fallback for environments with pre-ES5 implementations. - if (nativeParseInt(whitespace + '08') != 8) { - parseInt = function(string, radix, guard) { - // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. - // Chrome fails to trim leading whitespace characters. - // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. - if (guard ? isIterateeCall(string, radix, guard) : radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - string = trim(string); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); - }; + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } /** @@ -10468,7 +10530,7 @@ if (n % 2) { result += string; } - n = floor(n / 2); + n = nativeFloor(n / 2); string += string; } while (n); @@ -10653,7 +10715,7 @@ var settings = lodash.templateSettings; if (otherOptions && isIterateeCall(string, options, otherOptions)) { - options = otherOptions = null; + options = otherOptions = undefined; } string = baseToString(string); options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); @@ -10889,7 +10951,7 @@ */ function trunc(string, options, guard) { if (guard && isIterateeCall(string, options, guard)) { - options = null; + options = undefined; } var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; @@ -10984,7 +11046,7 @@ */ function words(string, pattern, guard) { if (guard && isIterateeCall(string, pattern, guard)) { - pattern = null; + pattern = undefined; } string = baseToString(string); return string.match(pattern || reWords) || []; @@ -11060,7 +11122,7 @@ */ function callback(func, thisArg, guard) { if (guard && isIterateeCall(func, thisArg, guard)) { - thisArg = null; + thisArg = undefined; } return isObjectLike(func) ? matches(func) @@ -11261,8 +11323,8 @@ function mixin(object, source, options) { if (options == null) { var isObj = isObject(source), - props = isObj ? keys(source) : null, - methodNames = (props && props.length) ? baseFunctions(source, props) : null; + props = isObj ? keys(source) : undefined, + methodNames = (props && props.length) ? baseFunctions(source, props) : undefined; if (!(methodNames ? methodNames.length : isObj)) { methodNames = false; @@ -11301,9 +11363,7 @@ result.__chain__ = chainAll; return result; } - var args = [this.value()]; - push.apply(args, arguments); - return func.apply(object, args); + return func.apply(object, arrayPush([this.value()], arguments)); }; }(func)); } @@ -11324,7 +11384,7 @@ * var lodash = _.noConflict(); */ function noConflict() { - context._ = oldDash; + root._ = oldDash; return this; } @@ -11433,7 +11493,7 @@ */ function range(start, end, step) { if (step && isIterateeCall(start, end, step)) { - end = step = null; + end = step = undefined; } start = +start || 0; step = step == null ? 1 : (+step || 0); @@ -11447,7 +11507,7 @@ // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (++index < length) { @@ -11485,7 +11545,7 @@ * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { - n = floor(n); + n = nativeFloor(n); // Exit early to avoid a JSC JIT bug in Safari 8 // where `Array(0)` is treated as `Array(1)`. @@ -11547,6 +11607,50 @@ return (+augend || 0) + (+addend || 0); } + /** + * Calculates `n` rounded up to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + /** + * Calculates `n` rounded down to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + /** * Gets the maximum value of `collection`. If `collection` is empty or falsey * `-Infinity` is returned. If an iteratee function is provided it is invoked @@ -11645,6 +11749,28 @@ */ var min = createExtremum(lt, POSITIVE_INFINITY); + /** + * Calculates `n` rounded to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + /** * Gets the sum of the values in `collection`. * @@ -11679,17 +11805,11 @@ */ function sum(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } - var callback = getCallback(), - noIteratee = iteratee == null; - - if (!(noIteratee && callback === baseCallback)) { - noIteratee = false; - iteratee = callback(iteratee, thisArg, 3); - } - return noIteratee - ? arraySum(isArray(collection) ? collection : toIterable(collection)) + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 + ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); } @@ -11736,6 +11856,7 @@ lodash.curryRight = curryRight; lodash.debounce = debounce; lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; @@ -11774,6 +11895,7 @@ lodash.method = method; lodash.methodOf = methodOf; lodash.mixin = mixin; + lodash.modArgs = modArgs; lodash.negate = negate; lodash.omit = omit; lodash.once = once; @@ -11849,6 +11971,7 @@ lodash.attempt = attempt; lodash.camelCase = camelCase; lodash.capitalize = capitalize; + lodash.ceil = ceil; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.deburr = deburr; @@ -11864,6 +11987,7 @@ lodash.findLastKey = findLastKey; lodash.findWhere = findWhere; lodash.first = first; + lodash.floor = floor; lodash.get = get; lodash.gt = gt; lodash.gte = gte; @@ -11912,6 +12036,7 @@ lodash.reduceRight = reduceRight; lodash.repeat = repeat; lodash.result = result; + lodash.round = round; lodash.runInContext = runInContext; lodash.size = size; lodash.snakeCase = snakeCase; @@ -11982,48 +12107,20 @@ lodash[methodName].placeholder = lodash; }); - // Add `LazyWrapper` methods that accept an `iteratee` value. - arrayEach(['dropWhile', 'filter', 'map', 'takeWhile'], function(methodName, type) { - var isFilter = type != LAZY_MAP_FLAG, - isDropWhile = type == LAZY_DROP_WHILE_FLAG; - - LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { - var filtered = this.__filtered__, - result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(), - iteratees = result.__iteratees__ || (result.__iteratees__ = []); - - iteratees.push({ - 'done': false, - 'count': 0, - 'index': 0, - 'iteratee': getCallback(iteratee, thisArg, 1), - 'limit': -1, - 'type': type - }); - - result.__filtered__ = filtered || isFilter; - return result; - }; - }); - // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. arrayEach(['drop', 'take'], function(methodName, index) { - var whileName = methodName + 'While'; - LazyWrapper.prototype[methodName] = function(n) { - var filtered = this.__filtered__, - result = (filtered && !index) ? this.dropWhile() : this.clone(); + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); - n = n == null ? 1 : nativeMax(floor(n) || 0, 0); + var result = this.clone(); if (filtered) { - if (index) { - result.__takeCount__ = nativeMin(result.__takeCount__, n); - } else { - last(result.__iteratees__).limit = n; - } + result.__takeCount__ = nativeMin(result.__takeCount__, n); } else { - var views = result.__views__ || (result.__views__ = []); - views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); + result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); } return result; }; @@ -12031,9 +12128,18 @@ LazyWrapper.prototype[methodName + 'Right'] = function(n) { return this.reverse()[methodName](n).reverse(); }; + }); - LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) { - return this.reverse()[whileName](predicate, thisArg).reverse(); + // Add `LazyWrapper` methods that accept an `iteratee` value. + arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var type = index + 1, + isFilter = type != LAZY_MAP_FLAG; + + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; }; }); @@ -12051,7 +12157,7 @@ var dropName = 'drop' + (index ? '' : 'Right'); LazyWrapper.prototype[methodName] = function() { - return this[dropName](1); + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); }; }); @@ -12080,10 +12186,13 @@ start = start == null ? 0 : (+start || 0); var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } if (start < 0) { - result = this.takeRight(-start); + result = result.takeRight(-start); } else if (start) { - result = this.drop(start); + result = result.drop(start); } if (end !== undefined) { end = (+end || 0); @@ -12092,21 +12201,25 @@ return result; }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { - return this.drop(0); + return this.take(POSITIVE_INFINITY); }; // Add `LazyWrapper` methods to `lodash.prototype`. baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var lodashFunc = lodash[methodName]; + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), + retUnwrapped = /^(?:first|last)$/.test(methodName), + lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName]; + if (!lodashFunc) { return; } - var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), - retUnwrapped = /^(?:first|last)$/.test(methodName); - lodash.prototype[methodName] = function() { - var args = arguments, + var args = retUnwrapped ? [1] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, @@ -12115,28 +12228,30 @@ useLazy = isLazy || isArray(value); if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { - // avoid lazy use if the iteratee has a "length" value other than `1` + // Avoid lazy use if the iteratee has a "length" value other than `1`. isLazy = useLazy = false; } - var onlyLazy = isLazy && !isHybrid; - if (retUnwrapped && !chainAll) { - return onlyLazy - ? func.call(value) - : lodashFunc.call(lodash, this.value()); - } var interceptor = function(value) { - var otherArgs = [value]; - push.apply(otherArgs, args); - return lodashFunc.apply(lodash, otherArgs); + return (retUnwrapped && chainAll) + ? lodashFunc(value, 1)[0] + : lodashFunc.apply(undefined, arrayPush([value], args)); }; - if (useLazy) { - var wrapper = onlyLazy ? value : new LazyWrapper(this), - result = func.apply(wrapper, args); - if (!retUnwrapped && (isHybrid || result.__actions__)) { - var actions = result.__actions__ || (result.__actions__ = []); - actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash }); + var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined }, + onlyLazy = isLazy && !isHybrid; + + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); return new LodashWrapper(result, chainAll); } return this.thru(interceptor); @@ -12144,7 +12259,7 @@ }); // Add `Array` and `String` methods to `lodash.prototype`. - arrayEach(['concat', 'join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { + arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); @@ -12171,7 +12286,7 @@ } }); - realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }]; + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; // Add functions to the lazy wrapper. LazyWrapper.prototype.clone = lazyClone; @@ -12181,6 +12296,7 @@ // Add chaining functions to the `lodash` wrapper. lodash.prototype.chain = wrapperChain; lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; lodash.prototype.plant = wrapperPlant; lodash.prototype.reverse = wrapperReverse; lodash.prototype.toString = wrapperToString; diff --git a/math.js b/math.js index a0f97cba9..1aa9da59d 100644 --- a/math.js +++ b/math.js @@ -1,8 +1,11 @@ -define(['./math/add', './math/max', './math/min', './math/sum'], function(add, max, min, sum) { +define(['./math/add', './math/ceil', './math/floor', './math/max', './math/min', './math/round', './math/sum'], function(add, ceil, floor, max, min, round, sum) { return { 'add': add, + 'ceil': ceil, + 'floor': floor, 'max': max, 'min': min, + 'round': round, 'sum': sum }; }); diff --git a/math/ceil.js b/math/ceil.js new file mode 100644 index 000000000..12063c75d --- /dev/null +++ b/math/ceil.js @@ -0,0 +1,26 @@ +define(['../internal/createRound'], function(createRound) { + + /** + * Calculates `n` rounded up to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + return ceil; +}); diff --git a/math/floor.js b/math/floor.js new file mode 100644 index 000000000..eb1d97649 --- /dev/null +++ b/math/floor.js @@ -0,0 +1,26 @@ +define(['../internal/createRound'], function(createRound) { + + /** + * Calculates `n` rounded down to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + + return floor; +}); diff --git a/math/round.js b/math/round.js new file mode 100644 index 000000000..32cf6479f --- /dev/null +++ b/math/round.js @@ -0,0 +1,26 @@ +define(['../internal/createRound'], function(createRound) { + + /** + * Calculates `n` rounded to `precision`. + * + * @static + * @memberOf _ + * @category Math + * @param {number} n The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + + return round; +}); diff --git a/math/sum.js b/math/sum.js index 919c5258c..962ae59f9 100644 --- a/math/sum.js +++ b/math/sum.js @@ -1,5 +1,8 @@ define(['../internal/arraySum', '../internal/baseCallback', '../internal/baseSum', '../lang/isArray', '../internal/isIterateeCall', '../internal/toIterable'], function(arraySum, baseCallback, baseSum, isArray, isIterateeCall, toIterable) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Gets the sum of the values in `collection`. * @@ -34,13 +37,11 @@ define(['../internal/arraySum', '../internal/baseCallback', '../internal/baseSum */ function sum(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = null; + iteratee = undefined; } - var noIteratee = iteratee == null; - - iteratee = noIteratee ? iteratee : baseCallback(iteratee, thisArg, 3); - return noIteratee - ? arraySum(isArray(collection) ? collection : toIterable(collection)) + iteratee = baseCallback(iteratee, thisArg, 3); + return iteratee.length == 1 + ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); } diff --git a/number/inRange.js b/number/inRange.js index 9c74c28b2..1143849d3 100644 --- a/number/inRange.js +++ b/number/inRange.js @@ -1,5 +1,8 @@ define([], function() { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /* Native method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max, nativeMin = Math.min; @@ -37,7 +40,7 @@ define([], function() { */ function inRange(value, start, end) { start = +start || 0; - if (typeof end === 'undefined') { + if (end === undefined) { end = start; start = 0; } else { diff --git a/number/random.js b/number/random.js index aa7266441..86dc9ed56 100644 --- a/number/random.js +++ b/number/random.js @@ -1,5 +1,8 @@ define(['../internal/baseRandom', '../internal/isIterateeCall'], function(baseRandom, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /* Native method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min, nativeRandom = Math.random; @@ -33,7 +36,7 @@ define(['../internal/baseRandom', '../internal/isIterateeCall'], function(baseRa */ function random(min, max, floating) { if (floating && isIterateeCall(min, max, floating)) { - max = floating = null; + max = floating = undefined; } var noMin = min == null, noMax = max == null; diff --git a/object.js b/object.js index 91d7045c7..0a4a8212a 100644 --- a/object.js +++ b/object.js @@ -1,8 +1,9 @@ -define(['./object/assign', './object/create', './object/defaults', './object/extend', './object/findKey', './object/findLastKey', './object/forIn', './object/forInRight', './object/forOwn', './object/forOwnRight', './object/functions', './object/get', './object/has', './object/invert', './object/keys', './object/keysIn', './object/mapKeys', './object/mapValues', './object/merge', './object/methods', './object/omit', './object/pairs', './object/pick', './object/result', './object/set', './object/transform', './object/values', './object/valuesIn'], function(assign, create, defaults, extend, findKey, findLastKey, forIn, forInRight, forOwn, forOwnRight, functions, get, has, invert, keys, keysIn, mapKeys, mapValues, merge, methods, omit, pairs, pick, result, set, transform, values, valuesIn) { +define(['./object/assign', './object/create', './object/defaults', './object/defaultsDeep', './object/extend', './object/findKey', './object/findLastKey', './object/forIn', './object/forInRight', './object/forOwn', './object/forOwnRight', './object/functions', './object/get', './object/has', './object/invert', './object/keys', './object/keysIn', './object/mapKeys', './object/mapValues', './object/merge', './object/methods', './object/omit', './object/pairs', './object/pick', './object/result', './object/set', './object/transform', './object/values', './object/valuesIn'], function(assign, create, defaults, defaultsDeep, extend, findKey, findLastKey, forIn, forInRight, forOwn, forOwnRight, functions, get, has, invert, keys, keysIn, mapKeys, mapValues, merge, methods, omit, pairs, pick, result, set, transform, values, valuesIn) { return { 'assign': assign, 'create': create, 'defaults': defaults, + 'defaultsDeep': defaultsDeep, 'extend': extend, 'findKey': findKey, 'findLastKey': findLastKey, diff --git a/object/assign.js b/object/assign.js index a2deebb20..2a413afb1 100644 --- a/object/assign.js +++ b/object/assign.js @@ -8,7 +8,7 @@ define(['../internal/assignWith', '../internal/baseAssign', '../internal/createA * (objectValue, sourceValue, key, object, source). * * **Note:** This method mutates `object` and is based on - * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). + * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). * * @static * @memberOf _ diff --git a/object/create.js b/object/create.js index e0da500ea..c5babe0b0 100644 --- a/object/create.js +++ b/object/create.js @@ -1,5 +1,8 @@ define(['../internal/baseAssign', '../internal/baseCreate', '../internal/isIterateeCall'], function(baseAssign, baseCreate, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates an object that inherits from the given `prototype` object. If a * `properties` object is provided its own enumerable properties are assigned @@ -37,7 +40,7 @@ define(['../internal/baseAssign', '../internal/baseCreate', '../internal/isItera function create(prototype, properties, guard) { var result = baseCreate(prototype); if (guard && isIterateeCall(prototype, properties, guard)) { - properties = null; + properties = undefined; } return properties ? baseAssign(result, properties) : result; } diff --git a/object/defaults.js b/object/defaults.js index ab394a990..a3f52cf4e 100644 --- a/object/defaults.js +++ b/object/defaults.js @@ -1,7 +1,4 @@ -define(['./assign', '../internal/assignDefaults', '../function/restParam'], function(assign, assignDefaults, restParam) { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; +define(['./assign', '../internal/assignDefaults', '../internal/createDefaults'], function(assign, assignDefaults, createDefaults) { /** * Assigns own enumerable properties of source object(s) to the destination @@ -21,14 +18,7 @@ define(['./assign', '../internal/assignDefaults', '../function/restParam'], func * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ - var defaults = restParam(function(args) { - var object = args[0]; - if (object == null) { - return object; - } - args.push(assignDefaults); - return assign.apply(undefined, args); - }); + var defaults = createDefaults(assign, assignDefaults); return defaults; }); diff --git a/object/defaultsDeep.js b/object/defaultsDeep.js new file mode 100644 index 000000000..d3e276f2b --- /dev/null +++ b/object/defaultsDeep.js @@ -0,0 +1,24 @@ +define(['../internal/createDefaults', './merge', '../internal/mergeDefaults'], function(createDefaults, merge, mergeDefaults) { + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); + * // => { 'user': { 'name': 'barney', 'age': 36 } } + * + */ + var defaultsDeep = createDefaults(merge, mergeDefaults); + + return defaultsDeep; +}); diff --git a/object/invert.js b/object/invert.js index dc0c2e05c..6b4f0b071 100644 --- a/object/invert.js +++ b/object/invert.js @@ -1,5 +1,8 @@ define(['../internal/isIterateeCall', './keys'], function(isIterateeCall, keys) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used for native method references. */ var objectProto = Object.prototype; @@ -31,7 +34,7 @@ define(['../internal/isIterateeCall', './keys'], function(isIterateeCall, keys) */ function invert(object, multiValue, guard) { if (guard && isIterateeCall(object, multiValue, guard)) { - multiValue = null; + multiValue = undefined; } var index = -1, props = keys(object), diff --git a/object/keys.js b/object/keys.js index 4ce3ce649..9e3f4653d 100644 --- a/object/keys.js +++ b/object/keys.js @@ -1,5 +1,8 @@ define(['../internal/getNative', '../internal/isArrayLike', '../lang/isObject', '../internal/shimKeys'], function(getNative, isArrayLike, isObject, shimKeys) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /* Native method references for those with the same name as other `lodash` methods. */ var nativeKeys = getNative(Object, 'keys'); @@ -7,7 +10,7 @@ define(['../internal/getNative', '../internal/isArrayLike', '../lang/isObject', * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static @@ -31,7 +34,7 @@ define(['../internal/getNative', '../internal/isArrayLike', '../lang/isObject', * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object == null ? null : object.constructor; + var Ctor = object == null ? undefined : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); diff --git a/object/transform.js b/object/transform.js index 436faf2ed..32a1606bb 100644 --- a/object/transform.js +++ b/object/transform.js @@ -1,5 +1,8 @@ define(['../internal/arrayEach', '../internal/baseCallback', '../internal/baseCreate', '../internal/baseForOwn', '../lang/isArray', '../lang/isFunction', '../lang/isObject', '../lang/isTypedArray'], function(arrayEach, baseCallback, baseCreate, baseForOwn, isArray, isFunction, isObject, isTypedArray) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own enumerable @@ -39,7 +42,7 @@ define(['../internal/arrayEach', '../internal/baseCallback', '../internal/baseCr if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } } else { accumulator = {}; diff --git a/package.json b/package.json index 2765c7dca..12694b3ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "3.9.3", + "version": "3.10.0", "main": "main.js", "private": true, "volo": { diff --git a/string/escapeRegExp.js b/string/escapeRegExp.js index c2f20ed86..b6fcf75e1 100644 --- a/string/escapeRegExp.js +++ b/string/escapeRegExp.js @@ -1,11 +1,10 @@ -define(['../internal/baseToString'], function(baseToString) { +define(['../internal/baseToString', '../internal/escapeRegExpChar'], function(baseToString, escapeRegExpChar) { /** - * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). - * In addition to special characters the forward slash is escaped to allow for - * easier `eval` use and `Function` compilation. + * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) + * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). */ - var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** @@ -25,8 +24,8 @@ define(['../internal/baseToString'], function(baseToString) { function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, '\\$&') - : string; + ? string.replace(reRegExpChars, escapeRegExpChar) + : (string || '(?:)'); } return escapeRegExp; diff --git a/string/pad.js b/string/pad.js index df116b20b..2c7a53f58 100644 --- a/string/pad.js +++ b/string/pad.js @@ -1,11 +1,9 @@ define(['../internal/baseToString', '../internal/createPadding', '../internal/root'], function(baseToString, createPadding, root) { - /** Native method references. */ - var ceil = Math.ceil, - floor = Math.floor; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsFinite = root.isFinite; + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeIsFinite = root.isFinite; /** * Pads `string` on the left and right sides if it's shorter than `length`. @@ -38,8 +36,8 @@ define(['../internal/baseToString', '../internal/createPadding', '../internal/ro return string; } var mid = (length - strLength) / 2, - leftLength = floor(mid), - rightLength = ceil(mid); + leftLength = nativeFloor(mid), + rightLength = nativeCeil(mid); chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; diff --git a/string/parseInt.js b/string/parseInt.js index 992940db4..d6a8d3846 100644 --- a/string/parseInt.js +++ b/string/parseInt.js @@ -3,18 +3,6 @@ define(['../internal/isIterateeCall', '../internal/root', './trim'], function(is /** Used to detect hexadecimal string values. */ var reHasHexPrefix = /^0[xX]/; - /** Used to detect and test for whitespace. */ - var whitespace = ( - // Basic whitespace characters. - ' \t\x0b\f\xa0\ufeff' + - - // Line terminators. - '\n\r\u2028\u2029' + - - // Unicode category "Zs" space separators. - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); - /* Native method references for those with the same name as other `lodash` methods. */ var nativeParseInt = root.parseInt; @@ -42,25 +30,16 @@ define(['../internal/isIterateeCall', '../internal/root', './trim'], function(is * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - if (guard && isIterateeCall(string, radix, guard)) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { radix = 0; + } else if (radix) { + radix = +radix; } - return nativeParseInt(string, radix); - } - // Fallback for environments with pre-ES5 implementations. - if (nativeParseInt(whitespace + '08') != 8) { - parseInt = function(string, radix, guard) { - // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. - // Chrome fails to trim leading whitespace characters. - // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. - if (guard ? isIterateeCall(string, radix, guard) : radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - string = trim(string); - return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); - }; + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } return parseInt; diff --git a/string/repeat.js b/string/repeat.js index 5e1f90ad1..8b9f0defb 100644 --- a/string/repeat.js +++ b/string/repeat.js @@ -1,10 +1,8 @@ define(['../internal/baseToString', '../internal/root'], function(baseToString, root) { - /** Native method references. */ - var floor = Math.floor; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsFinite = root.isFinite; + var nativeFloor = Math.floor, + nativeIsFinite = root.isFinite; /** * Repeats the given string `n` times. @@ -39,7 +37,7 @@ define(['../internal/baseToString', '../internal/root'], function(baseToString, if (n % 2) { result += string; } - n = floor(n / 2); + n = nativeFloor(n / 2); string += string; } while (n); diff --git a/string/template.js b/string/template.js index b2e1cfd7c..597f6e7cb 100644 --- a/string/template.js +++ b/string/template.js @@ -8,7 +8,7 @@ define(['../internal/assignOwnDefaults', '../internal/assignWith', '../utility/a reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; - /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ + /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to ensure capturing order of template delimiters. */ @@ -119,7 +119,7 @@ define(['../internal/assignOwnDefaults', '../internal/assignWith', '../utility/a var settings = templateSettings.imports._.templateSettings || templateSettings; if (otherOptions && isIterateeCall(string, options, otherOptions)) { - options = otherOptions = null; + options = otherOptions = undefined; } string = baseToString(string); options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); diff --git a/string/trunc.js b/string/trunc.js index a8d0b53a4..6af35267c 100644 --- a/string/trunc.js +++ b/string/trunc.js @@ -1,5 +1,8 @@ define(['../internal/baseToString', '../internal/isIterateeCall', '../lang/isObject', '../lang/isRegExp'], function(baseToString, isIterateeCall, isObject, isRegExp) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used as default options for `_.trunc`. */ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = '...'; @@ -49,7 +52,7 @@ define(['../internal/baseToString', '../internal/isIterateeCall', '../lang/isObj */ function trunc(string, options, guard) { if (guard && isIterateeCall(string, options, guard)) { - options = null; + options = undefined; } var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; diff --git a/string/words.js b/string/words.js index 0f06f2fe5..628d76376 100644 --- a/string/words.js +++ b/string/words.js @@ -1,5 +1,8 @@ define(['../internal/baseToString', '../internal/isIterateeCall'], function(baseToString, isIterateeCall) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** Used to match words to create compound words. */ var reWords = (function() { var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]', @@ -28,7 +31,7 @@ define(['../internal/baseToString', '../internal/isIterateeCall'], function(base */ function words(string, pattern, guard) { if (guard && isIterateeCall(string, pattern, guard)) { - pattern = null; + pattern = undefined; } string = baseToString(string); return string.match(pattern || reWords) || []; diff --git a/support.js b/support.js index f2141836e..df2f8dd6d 100644 --- a/support.js +++ b/support.js @@ -1,7 +1,4 @@ -define(['./internal/root'], function(root) { - - /** Used to detect DOM support. */ - var document = (document = root.window) ? document.document : null; +define([], function() { /** * An object environment feature flags. @@ -12,26 +9,5 @@ define(['./internal/root'], function(root) { */ var support = {}; - (function(x) { - var Ctor = function() { this.x = x; }, - object = { '0': x, 'length': x }, - props = []; - - Ctor.prototype = { 'valueOf': x, 'y': x }; - for (var key in new Ctor) { props.push(key); } - - /** - * Detect if the DOM is supported. - * - * @memberOf _.support - * @type boolean - */ - try { - support.dom = document.createDocumentFragment().nodeType === 11; - } catch(e) { - support.dom = false; - } - }(1, 0)); - return support; }); diff --git a/utility/callback.js b/utility/callback.js index 977de379c..a1aeb7a9c 100644 --- a/utility/callback.js +++ b/utility/callback.js @@ -1,5 +1,8 @@ define(['../internal/baseCallback', '../internal/isIterateeCall', '../internal/isObjectLike', './matches'], function(baseCallback, isIterateeCall, isObjectLike, matches) { + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and arguments of the created function. If `func` is a property name the @@ -40,7 +43,7 @@ define(['../internal/baseCallback', '../internal/isIterateeCall', '../internal/i */ function callback(func, thisArg, guard) { if (guard && isIterateeCall(func, thisArg, guard)) { - thisArg = null; + thisArg = undefined; } return isObjectLike(func) ? matches(func) diff --git a/utility/mixin.js b/utility/mixin.js index c6ec3e721..7589357d9 100644 --- a/utility/mixin.js +++ b/utility/mixin.js @@ -1,10 +1,4 @@ -define(['../internal/arrayCopy', '../internal/baseFunctions', '../lang/isFunction', '../lang/isObject', '../object/keys'], function(arrayCopy, baseFunctions, isFunction, isObject, keys) { - - /** Used for native method references. */ - var arrayProto = Array.prototype; - - /** Native method references. */ - var push = arrayProto.push; +define(['../internal/arrayCopy', '../internal/arrayPush', '../internal/baseFunctions', '../lang/isFunction', '../lang/isObject', '../object/keys'], function(arrayCopy, arrayPush, baseFunctions, isFunction, isObject, keys) { /** * Adds all own enumerable function properties of a source object to the @@ -72,9 +66,7 @@ define(['../internal/arrayCopy', '../internal/baseFunctions', '../lang/isFunctio result.__chain__ = chainAll; return result; } - var args = [this.value()]; - push.apply(args, arguments); - return func.apply(object, args); + return func.apply(object, arrayPush([this.value()], arguments)); }; }(func)); } diff --git a/utility/range.js b/utility/range.js index ab6825f36..56e1f0ef6 100644 --- a/utility/range.js +++ b/utility/range.js @@ -1,10 +1,11 @@ define(['../internal/isIterateeCall'], function(isIterateeCall) { - /** Native method references. */ - var ceil = Math.ceil; + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; /* Native method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max; + var nativeCeil = Math.ceil, + nativeMax = Math.max; /** * Creates an array of numbers (positive and/or negative) progressing from @@ -41,7 +42,7 @@ define(['../internal/isIterateeCall'], function(isIterateeCall) { */ function range(start, end, step) { if (step && isIterateeCall(start, end, step)) { - end = step = null; + end = step = undefined; } start = +start || 0; step = step == null ? 1 : (+step || 0); @@ -55,7 +56,7 @@ define(['../internal/isIterateeCall'], function(isIterateeCall) { // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. var index = -1, - length = nativeMax(ceil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (++index < length) { diff --git a/utility/times.js b/utility/times.js index de17e3227..a2c8f427a 100644 --- a/utility/times.js +++ b/utility/times.js @@ -1,10 +1,8 @@ define(['../internal/bindCallback', '../internal/root'], function(bindCallback, root) { - /** Native method references. */ - var floor = Math.floor; - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsFinite = root.isFinite, + var nativeFloor = Math.floor, + nativeIsFinite = root.isFinite, nativeMin = Math.min; /** Used as references for the maximum length and index of an array. */ @@ -38,7 +36,7 @@ define(['../internal/bindCallback', '../internal/root'], function(bindCallback, * // => also invokes `mage.castSpell(n)` three times */ function times(n, iteratee, thisArg) { - n = floor(n); + n = nativeFloor(n); // Exit early to avoid a JSC JIT bug in Safari 8 // where `Array(0)` is treated as `Array(1)`.