From f84f83a4a573b855589115a6fd5a9bd74b6eeecb Mon Sep 17 00:00:00 2001 From: jdalton Date: Thu, 7 May 2015 01:47:27 -0700 Subject: [PATCH] Bump to v3.9.0. --- README.md | 11 +- array/intersection.js | 37 +- array/zipWith.js | 4 +- chain/lodash.js | 41 +- collection/invoke.js | 4 +- collection/map.js | 2 +- collection/reduce.js | 2 +- date/now.js | 4 +- function/debounce.js | 13 +- function/memoize.js | 6 +- function/throttle.js | 12 +- index.js | 1009 +++++++++---------- internal/SetCache.js | 6 +- internal/arrayExtremum.js | 30 + internal/arrayMax.js | 25 - internal/arrayMin.js | 25 - internal/assignWith.js | 13 +- internal/baseAssign.js | 34 +- internal/baseAt.js | 2 +- internal/baseCompareAscending.js | 19 +- internal/baseCreate.js | 10 +- internal/{extremumBy.js => baseExtremum.js} | 22 +- internal/baseGet.js | 6 +- internal/baseIsEqual.js | 12 +- internal/baseIsEqualDeep.js | 8 +- internal/baseIsMatch.js | 49 +- internal/baseMatches.js | 41 +- internal/baseMatchesProperty.js | 12 +- internal/baseMerge.js | 17 +- internal/basePullAt.js | 2 +- internal/baseToString.js | 2 +- internal/binaryIndex.js | 4 +- internal/binaryIndexBy.js | 10 +- internal/bufferClone.js | 12 +- internal/charAtCallback.js | 12 - internal/createAssigner.js | 10 +- internal/createCache.js | 6 +- internal/createCtorWrapper.js | 14 +- internal/createExtremum.js | 32 +- internal/createFlow.js | 17 +- internal/createHybridWrapper.js | 17 +- internal/equalArrays.js | 47 +- internal/equalObjects.js | 37 +- internal/getFuncName.js | 38 +- internal/getMatchData.js | 21 + internal/getNative.js | 16 + internal/getSymbols.js | 19 - internal/isIndex.js | 4 +- internal/isLength.js | 2 +- internal/metaMap.js | 4 +- internal/shimKeys.js | 7 +- internal/toIterable.js | 2 +- internal/toObject.js | 2 +- internal/toPath.js | 2 +- lang.js | 5 + lang/clone.js | 5 +- lang/cloneDeep.js | 5 +- lang/eq.js | 1 + lang/gt.js | 25 + lang/gte.js | 25 + lang/isArray.js | 6 +- lang/isEqual.js | 11 +- lang/isFinite.js | 4 +- lang/isFunction.js | 4 +- lang/isMatch.js | 33 +- lang/isNative.js | 7 +- lang/isObject.js | 2 +- lang/isPlainObject.js | 8 +- lang/lt.js | 25 + lang/lte.js | 25 + math/max.js | 6 +- math/min.js | 6 +- object/get.js | 2 +- object/has.js | 12 +- object/keys.js | 8 +- object/keysIn.js | 5 +- object/pairs.js | 5 +- object/transform.js | 2 +- package.json | 2 +- string/escape.js | 2 +- string/pad.js | 2 +- string/padLeft.js | 2 +- string/padRight.js | 2 +- string/trunc.js | 2 +- support.js | 45 +- utility/matchesProperty.js | 6 +- utility/mixin.js | 3 - utility/times.js | 2 +- 88 files changed, 1022 insertions(+), 1098 deletions(-) create mode 100644 internal/arrayExtremum.js delete mode 100644 internal/arrayMax.js delete mode 100644 internal/arrayMin.js rename internal/{extremumBy.js => baseExtremum.js} (50%) delete mode 100644 internal/charAtCallback.js create mode 100644 internal/getMatchData.js create mode 100644 internal/getNative.js delete mode 100644 internal/getSymbols.js create mode 100644 lang/eq.js create mode 100644 lang/gt.js create mode 100644 lang/gte.js create mode 100644 lang/lt.js create mode 100644 lang/lte.js diff --git a/README.md b/README.md index 701a14b6b..37cfa002c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# lodash v3.8.0 +# lodash v3.9.0 The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) exported as [Node.js](http://nodejs.org/)/[io.js](https://iojs.org/) modules. @@ -28,7 +28,7 @@ var array = require('lodash/array'); var chunk = require('lodash/array/chunk'); ``` -See the [package source](https://github.com/lodash/lodash/tree/3.8.0-npm) for more details. +See the [package source](https://github.com/lodash/lodash/tree/3.9.0-npm) for more details. **Note:**
Don’t assign values to the [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL.
@@ -39,8 +39,8 @@ Install [n_](https://www.npmjs.com/package/n_) for a REPL that includes lodash b lodash is also available in a variety of other builds & module formats. * npm packages for [modern](https://www.npmjs.com/package/lodash), [compatibility](https://www.npmjs.com/package/lodash-compat), & [per method](https://www.npmjs.com/browse/keyword/lodash-modularized) builds - * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.8.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.8.0-amd) builds - * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.8.0-es) build + * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.9.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.9.0-amd) builds + * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.9.0-es) build ## Further Reading @@ -75,6 +75,7 @@ lodash is also available in a variety of other builds & module formats. * [_.forIn](https://lodash.com/docs#forIn) for iterating all enumerable properties * [_.forOwn](https://lodash.com/docs#forOwn) for iterating own properties * [_.get](https://lodash.com/docs#get) & [_.set](https://lodash.com/docs#set) for deep property getting & setting + * [_.gt](https://lodash.com/docs#gt), [_.gte](https://lodash.com/docs#gte), [_.lt](https://lodash.com/docs#lt), & [_.lte](https://lodash.com/docs#lte) relational methods * [_.inRange](https://lodash.com/docs#inRange) for checking whether a number is within a given range * [_.isNative](https://lodash.com/docs#isNative) to check for native functions * [_.isPlainObject](https://lodash.com/docs#isPlainObject) & [_.toPlainObject](https://lodash.com/docs#toPlainObject) to check for & convert to `Object` objects @@ -115,5 +116,5 @@ lodash is also available in a variety of other builds & module formats. ## Support -Tested in Chrome 41-42, Firefox 36-37, IE 6-11, MS Edge, Opera 27-28, Safari 5-8, io.js 1.8.1, Node.js 0.8.28, 0.10.38, & 0.12.2, PhantomJS 1.9.8, RingoJS 0.11, & Rhino 1.7RC5. +Tested in Chrome 41-42, Firefox 37-38, IE 6-11, MS Edge, Opera 28-29, Safari 5-8, ChakraNode 0.12.2, io.js 2.0.2, Node.js 0.8.28, 0.10.38, & 0.12.3, PhantomJS 1.9.8, RingoJS 0.11, & Rhino 1.7.6 Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. diff --git a/array/intersection.js b/array/intersection.js index 13af23eb5..aca423f77 100644 --- a/array/intersection.js +++ b/array/intersection.js @@ -1,7 +1,8 @@ var baseIndexOf = require('../internal/baseIndexOf'), cacheIndexOf = require('../internal/cacheIndexOf'), createCache = require('../internal/createCache'), - isArrayLike = require('../internal/isArrayLike'); + isArrayLike = require('../internal/isArrayLike'), + restParam = require('../function/restParam'); /** * Creates an array of unique values in all provided arrays using @@ -17,27 +18,19 @@ var baseIndexOf = require('../internal/baseIndexOf'), * _.intersection([1, 2], [4, 2], [2, 1]); * // => [2] */ -function intersection() { - var args = [], - argsIndex = -1, - argsLength = arguments.length, - caches = [], +var intersection = restParam(function(arrays) { + var othLength = arrays.length, + othIndex = othLength, + caches = Array(length), indexOf = baseIndexOf, isCommon = true, result = []; - while (++argsIndex < argsLength) { - var value = arguments[argsIndex]; - if (isArrayLike(value)) { - args.push(value); - caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null); - } + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; } - argsLength = args.length; - if (argsLength < 2) { - return result; - } - var array = args[0], + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; @@ -46,10 +39,10 @@ function intersection() { while (++index < length) { value = array[index]; if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { - argsIndex = argsLength; - while (--argsIndex) { - var cache = caches[argsIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { continue outer; } } @@ -60,6 +53,6 @@ function intersection() { } } return result; -} +}); module.exports = intersection; diff --git a/array/zipWith.js b/array/zipWith.js index 7a268df51..ad103742c 100644 --- a/array/zipWith.js +++ b/array/zipWith.js @@ -20,8 +20,8 @@ var restParam = require('../function/restParam'), */ var zipWith = restParam(function(arrays) { var length = arrays.length, - iteratee = arrays[length - 2], - thisArg = arrays[length - 1]; + iteratee = length > 2 ? arrays[length - 2] : undefined, + thisArg = length > 1 ? arrays[length - 1] : undefined; if (length > 2 && typeof iteratee == 'function') { length -= 2; diff --git a/chain/lodash.js b/chain/lodash.js index 7ca104c44..3241ed89f 100644 --- a/chain/lodash.js +++ b/chain/lodash.js @@ -50,30 +50,31 @@ var hasOwnProperty = objectProto.hasOwnProperty; * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`, - * `merge`, `mixin`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, - * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`, - * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, - * `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, - * `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, `where`, - * `without`, `wrap`, `xor`, `zip`, and `zipObject` + * `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` * * 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`, `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`, `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` + * `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` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. diff --git a/collection/invoke.js b/collection/invoke.js index 5cb428ec2..0a0a84cdb 100644 --- a/collection/invoke.js +++ b/collection/invoke.js @@ -5,7 +5,7 @@ var baseEach = require('../internal/baseEach'), restParam = require('../function/restParam'); /** - * Invokes the method at `path` on each element in `collection`, returning + * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments * are provided to each invoked method. If `methodName` is a function it is * invoked for, and `this` bound to, each element in `collection`. @@ -33,7 +33,7 @@ var invoke = restParam(function(collection, path, args) { result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : (isProp && value != null && value[path]); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; diff --git a/collection/map.js b/collection/map.js index 1413f50c9..5381110df 100644 --- a/collection/map.js +++ b/collection/map.js @@ -19,7 +19,7 @@ var arrayMap = require('../internal/arrayMap'), * callback returns `true` for elements that have the properties of the given * object, else `false`. * - * Many lodash methods are guarded to work as interatees for methods like + * Many lodash methods are guarded to work as iteratees for methods like * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. * * The guarded methods are: diff --git a/collection/reduce.js b/collection/reduce.js index a483d2568..da97655c1 100644 --- a/collection/reduce.js +++ b/collection/reduce.js @@ -10,7 +10,7 @@ var arrayReduce = require('../internal/arrayReduce'), * value. The `iteratee` is bound to `thisArg` and invoked with four arguments: * (accumulator, value, index|key, collection). * - * Many lodash methods are guarded to work as interatees for methods like + * Many lodash methods are guarded to work as iteratees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: diff --git a/date/now.js b/date/now.js index 628225d2a..ffe3060e5 100644 --- a/date/now.js +++ b/date/now.js @@ -1,7 +1,7 @@ -var isNative = require('../lang/isNative'); +var getNative = require('../internal/getNative'); /* Native method references for those with the same name as other `lodash` methods. */ -var nativeNow = isNative(nativeNow = Date.now) && nativeNow; +var nativeNow = getNative(Date, 'now'); /** * Gets the number of milliseconds that have elapsed since the Unix epoch diff --git a/function/debounce.js b/function/debounce.js index 5fdf7fce6..5df81e71a 100644 --- a/function/debounce.js +++ b/function/debounce.js @@ -8,12 +8,13 @@ var FUNC_ERROR_TEXT = 'Expected a function'; var nativeMax = Math.max; /** - * Creates a function that delays invoking `func` until after `wait` milliseconds - * have elapsed since the last time it was invoked. The created function comes - * with a `cancel` method to cancel delayed invocations. Provide an options - * object to indicate that `func` should be invoked on the leading and/or - * trailing edge of the `wait` timeout. Subsequent calls to the debounced - * function return the result of the last `func` invocation. + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed invocations. Provide an options object to indicate that `func` + * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * Subsequent calls to the debounced function return the result of the last + * `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the debounced function is diff --git a/function/memoize.js b/function/memoize.js index c9de9897c..1088e4be6 100644 --- a/function/memoize.js +++ b/function/memoize.js @@ -60,14 +60,14 @@ function memoize(func, resolver) { } var memoized = function() { var args = arguments, - cache = memoized.cache, - key = resolver ? resolver.apply(this, args) : args[0]; + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; if (cache.has(key)) { return cache.get(key); } var result = func.apply(this, args); - cache.set(key, result); + memoized.cache = cache.set(key, result); return result; }; memoized.cache = new memoize.Cache; diff --git a/function/throttle.js b/function/throttle.js index 7c30e646b..5e8f0ef56 100644 --- a/function/throttle.js +++ b/function/throttle.js @@ -12,12 +12,12 @@ var debounceOptions = { }; /** - * Creates a function that only invokes `func` at most once per every `wait` - * milliseconds. The created function comes with a `cancel` method to cancel - * delayed invocations. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. - * Subsequent calls to the throttled function return the result of the last - * `func` call. + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed invocations. Provide an options object to indicate + * that `func` should be invoked on the leading and/or trailing edge of the + * `wait` timeout. Subsequent calls to the throttled function return the + * result of the last `func` call. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the throttled function is diff --git a/index.js b/index.js index f52debbed..50464044c 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ /** * @license - * lodash 3.8.0 (Custom Build) + * lodash 3.9.0 (Custom Build) * Build: `lodash modern -d -o ./index.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.8.0'; + var VERSION = '3.9.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -275,7 +275,7 @@ /** * Used as a reference to the global object. * - * The `this` value is used if it is the global object to avoid Greasemonkey's + * The `this` value is used if it's the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this; @@ -285,19 +285,28 @@ * sorts them in ascending order without guaranteeing a stable sort. * * @private - * @param {*} value The value to compare to `other`. - * @param {*} other The value to compare to `value`. + * @param {*} value The value to compare. + * @param {*} other The other value to compare. * @returns {number} Returns the sort order indicator for `value`. */ function baseCompareAscending(value, other) { if (value !== other) { - var valIsReflexive = value === value, + var valIsNull = value === null, + valIsUndef = value === undefined, + valIsReflexive = value === value; + + var othIsNull = other === null, + othIsUndef = other === undefined, othIsReflexive = other === other; - if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) { + if ((value > other && !othIsNull) || !valIsReflexive || + (valIsNull && !othIsUndef && othIsReflexive) || + (valIsUndef && othIsReflexive)) { return 1; } - if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) { + if ((value < other && !valIsNull) || !othIsReflexive || + (othIsNull && !valIsUndef && valIsReflexive) || + (othIsUndef && valIsReflexive)) { return -1; } } @@ -365,7 +374,7 @@ } /** - * Converts `value` to a string if it is not one. An empty string is returned + * Converts `value` to a string if it's not one. An empty string is returned * for `null` or `undefined` values. * * @private @@ -379,17 +388,6 @@ return value == null ? '' : (value + ''); } - /** - * Used by `_.max` and `_.min` as the default callback for string values. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the code unit of the first character of the string. - */ - function charAtCallback(string) { - return string.charCodeAt(0); - } - /** * Used by `_.trim` and `_.trimLeft` to get the index of the first character * of `string` that is not found in `chars`. @@ -710,7 +708,7 @@ stringProto = String.prototype; /** Used to detect DOM support. */ - var document = (document = context.window) && document.document; + var document = (document = context.window) ? document.document : null; /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; @@ -732,26 +730,23 @@ /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(objToString) - .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + escapeRegExp(fnToString.call(hasOwnProperty)) + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references. */ - var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, - bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, + var ArrayBuffer = getNative(context, 'ArrayBuffer'), + bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, - getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols, - getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, + getPrototypeOf = getNative(Object, 'getPrototypeOf'), push = arrayProto.push, - preventExtensions = isNative(preventExtensions = Object.preventExtensions) && preventExtensions, - propertyIsEnumerable = objectProto.propertyIsEnumerable, - Set = isNative(Set = context.Set) && Set, + Set = getNative(context, 'Set'), setTimeout = context.setTimeout, splice = arrayProto.splice, - Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, - WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; + Uint8Array = getNative(context, 'Uint8Array'), + WeakMap = getNative(context, 'WeakMap'); /** Used to clone array buffers. */ var Float64Array = (function() { @@ -759,53 +754,29 @@ // where the array buffer's `byteLength` is not a multiple of the typed // array's `BYTES_PER_ELEMENT`. try { - var func = isNative(func = context.Float64Array) && func, + var func = getNative(context, 'Float64Array'), result = new func(new ArrayBuffer(10), 0, 1) && func; } catch(e) {} - return result; - }()); - - /** Used as `baseAssign`. */ - var nativeAssign = (function() { - // Avoid `Object.assign` in Firefox 34-37 which have an early implementation - // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344 - // for more details. - // - // Use `Object.preventExtensions` on a plain object instead of simply using - // `Object('x')` because Chrome and IE fail to throw an error when attempting - // to assign values to readonly indexes of strings. - var func = preventExtensions && isNative(func = Object.assign) && func; - try { - if (func) { - var object = preventExtensions({ '1': 0 }); - object[0] = 1; - } - } catch(e) { - // Only attempt in strict mode. - try { func(object, 'xo'); } catch(e) {} - return !object[1] && func; - } - return false; + return result || null; }()); /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, - nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, + var nativeCreate = getNative(Object, 'create'), + nativeIsArray = getNative(Array, 'isArray'), nativeIsFinite = context.isFinite, - nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, + nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, - nativeNow = isNative(nativeNow = Date.now) && nativeNow, - nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite, + nativeNow = getNative(Date, 'now'), + nativeNumIsFinite = getNative(Number, 'isFinite'), nativeParseInt = context.parseInt, nativeRandom = Math.random; /** Used as references for `-Infinity` and `Infinity`. */ - var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, - POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; /** Used as references for the maximum length and index of an array. */ - var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; @@ -816,7 +787,7 @@ * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * of an array-like value. */ - var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; + var MAX_SAFE_INTEGER = 9007199254740991; /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; @@ -863,30 +834,31 @@ * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, - * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`, - * `merge`, `mixin`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, - * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`, - * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, - * `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, - * `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, `where`, - * `without`, `wrap`, `xor`, `zip`, and `zipObject` + * `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` * * 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`, `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`, `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` + * `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` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. @@ -963,31 +935,12 @@ (function(x) { var Ctor = function() { this.x = x; }, - args = arguments, object = { '0': x, 'length': x }, props = []; Ctor.prototype = { 'valueOf': x, 'y': x }; for (var key in new Ctor) { props.push(key); } - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but Firefox OS certified apps, older Opera mobile browsers, and - * the PlayStation 3; forced `false` for Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = /\bthis\b/.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - /** * Detect if the DOM is supported. * @@ -999,24 +952,6 @@ } catch(e) { support.dom = false; } - - /** - * Detect if `arguments` object indexes are non-enumerable. - * - * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object - * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat - * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` - * checks for indexes that exceed the number of function parameters and - * whose associated argument values are `0`. - * - * @memberOf _.support - * @type boolean - */ - try { - support.nonEnumArgs = !propertyIsEnumerable.call(args, 1); - } catch(e) { - support.nonEnumArgs = true; - } }(1, 0)); /** @@ -1407,6 +1342,35 @@ return true; } + /** + * A specialized version of `baseExtremum` for arrays whichs invokes `iteratee` + * with one argument: (value). + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. + * @returns {*} Returns the extremum value. + */ + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, + length = array.length, + computed = exValue, + result = computed; + + while (++index < length) { + var value = array[index], + current = +iteratee(value); + + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + /** * A specialized version of `_.filter` for arrays without support for callback * shorthands and `this` binding. @@ -1451,48 +1415,6 @@ return result; } - /** - * A specialized version of `_.max` for arrays without support for iteratees. - * - * @private - * @param {Array} array The array to iterate over. - * @returns {*} Returns the maximum value. - */ - function arrayMax(array) { - var index = -1, - length = array.length, - result = NEGATIVE_INFINITY; - - while (++index < length) { - var value = array[index]; - if (value > result) { - result = value; - } - } - return result; - } - - /** - * A specialized version of `_.min` for arrays without support for iteratees. - * - * @private - * @param {Array} array The array to iterate over. - * @returns {*} Returns the minimum value. - */ - function arrayMin(array) { - var index = -1, - length = array.length, - result = POSITIVE_INFINITY; - - while (++index < length) { - var value = array[index]; - if (value < result) { - result = value; - } - } - return result; - } - /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands and `this` binding. @@ -1623,10 +1545,8 @@ * @returns {Object} Returns `object`. */ function assignWith(object, source, customizer) { - var props = keys(source); - push.apply(props, getSymbols(source)); - var index = -1, + props = keys(source), length = props.length; while (++index < length) { @@ -1651,11 +1571,11 @@ * @param {Object} source The source object. * @returns {Object} Returns `object`. */ - var baseAssign = nativeAssign || function(object, source) { + function baseAssign(object, source) { return source == null ? object - : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object)); - }; + : baseCopy(source, keys(source), object); + } /** * The base implementation of `_.at` without support for string collections @@ -1670,7 +1590,7 @@ var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), - length = isArr && collection.length, + length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); @@ -1811,14 +1731,14 @@ * @returns {Object} Returns the new object. */ var baseCreate = (function() { - function Object() {} + function object() {} return function(prototype) { if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; + object.prototype = prototype; + var result = new object; + object.prototype = null; } - return result || context.Object(); + return result || {}; }; }()); @@ -1927,6 +1847,32 @@ return result; } + /** + * Gets the extremum value of `collection` invoking `iteratee` for each value + * in `collection` to generate the criterion by which the value is ranked. + * The `iteratee` is invoked with three arguments: (value, index|key, collection). + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, + result = computed; + + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || (current === exValue && current === result)) { + computed = current; + result = value; + } + }); + return result; + } + /** * The base implementation of `_.fill` without an iteratee call guard. * @@ -2143,11 +2089,11 @@ if (pathKey !== undefined && pathKey in toObject(object)) { path = [pathKey]; } - var index = -1, + var index = 0, length = path.length; - while (object != null && ++index < length) { - object = object[path[index]]; + while (object != null && index < length) { + object = object[path[index++]]; } return (index && index == length) ? object : undefined; } @@ -2166,17 +2112,10 @@ * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { - // Exit early for identical values. if (value === other) { return true; } - var valType = typeof value, - othType = typeof other; - - // Exit early for unlike primitive values. - if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') || - value == null || other == null) { - // Return `false` unless both values are `NaN`. + if (value == null || other == null || (!isObject(value) && !isObject(other))) { return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); @@ -2227,11 +2166,11 @@ return equalByTag(object, other, objTag); } if (!isLoose) { - var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), - othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - if (valWrapped || othWrapped) { - return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); } } if (!isSameTag) { @@ -2266,41 +2205,43 @@ * * @private * @param {Object} object The object to inspect. - * @param {Array} props The source property names to match. - * @param {Array} values The source values to match. - * @param {Array} strictCompareFlags Strict comparison flags for source values. + * @param {Array} matchData The propery names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparing objects. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ - function baseIsMatch(object, props, values, strictCompareFlags, customizer) { - var index = -1, - length = props.length, + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, + length = index, noCustomizer = !customizer; - while (++index < length) { - if ((noCustomizer && strictCompareFlags[index]) - ? values[index] !== object[props[index]] - : !(props[index] in object) + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) ) { return false; } } - index = -1; while (++index < length) { - var key = props[index], + data = matchData[index]; + var key = data[0], objValue = object[key], - srcValue = values[index]; + srcValue = data[1]; - if (noCustomizer && strictCompareFlags[index]) { - var result = objValue !== undefined || (key in object); - } else { - result = customizer ? customizer(objValue, srcValue, key) : undefined; - if (result === undefined) { - result = baseIsEqual(srcValue, objValue, customizer, true); + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; } - } - if (!result) { - return false; } } return true; @@ -2333,35 +2274,20 @@ * @returns {Function} Returns the new function. */ function baseMatches(source) { - var props = keys(source), - length = props.length; + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], + value = matchData[0][1]; - if (!length) { - return constant(true); - } - if (length == 1) { - var key = props[0], - value = source[key]; - - if (isStrictComparable(value)) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === value && (value !== undefined || (key in toObject(object))); - }; - } - } - var values = Array(length), - strictCompareFlags = Array(length); - - while (length--) { - value = source[props[length]]; - values[length] = value; - strictCompareFlags[length] = isStrictComparable(value); + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || (key in toObject(object))); + }; } return function(object) { - return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags); + return baseIsMatch(object, matchData); }; } @@ -2371,12 +2297,12 @@ * * @private * @param {string} path The path of the property to get. - * @param {*} value The value to compare. + * @param {*} srcValue The value to compare. * @returns {Function} Returns the new function. */ - function baseMatchesProperty(path, value) { + function baseMatchesProperty(path, srcValue) { var isArr = isArray(path), - isCommon = isKey(path) && isStrictComparable(value), + isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = (path + ''); path = toPath(path); @@ -2394,9 +2320,9 @@ key = last(path); object = toObject(object); } - return object[key] === value - ? (value !== undefined || (key in object)) - : baseIsEqual(value, object[key], null, true); + return object[key] === srcValue + ? (srcValue !== undefined || (key in object)) + : baseIsEqual(srcValue, object[key], undefined, true); }; } @@ -2416,11 +2342,9 @@ if (!isObject(object)) { return object; } - var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)); - if (!isSrcArr) { - var props = keys(source); - push.apply(props, getSymbols(source)); - } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), + props = isSrcArr ? null : keys(source); + arrayEach(props || source, function(srcValue, key) { if (props) { key = srcValue; @@ -2439,7 +2363,7 @@ if (isCommon) { result = srcValue; } - if ((isSrcArr || result !== undefined) && + if ((result !== undefined || (isSrcArr && !(key in object))) && (isCommon || (result === result ? (result !== value) : (value === value)))) { object[key] = result; } @@ -2546,7 +2470,7 @@ function basePullAt(array, indexes) { var length = array ? indexes.length : 0; while (length--) { - var index = parseFloat(indexes[length]); + var index = indexes[length]; if (index != previous && isIndex(index)) { var previous = index; splice.call(array, index, 1); @@ -2859,7 +2783,7 @@ var mid = (low + high) >>> 1, computed = array[mid]; - if (retHighest ? (computed <= value) : (computed < value)) { + if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { low = mid + 1; } else { high = mid; @@ -2889,17 +2813,23 @@ var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, + valIsNull = value === null, valIsUndef = value === undefined; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), + isDef = computed !== undefined, isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); } else if (valIsUndef) { - setLow = isReflexive && (retHighest || computed !== undefined); + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); } @@ -3089,19 +3019,19 @@ return restParam(function(object, sources) { var index = -1, length = object == null ? 0 : sources.length, - customizer = length > 2 && sources[length - 2], - guard = length > 2 && sources[2], - thisArg = length > 1 && sources[length - 1]; + customizer = length > 2 ? sources[length - 2] : undefined, + guard = length > 2 ? sources[2] : undefined, + thisArg = length > 1 ? sources[length - 1] : undefined; if (typeof customizer == 'function') { customizer = bindCallback(customizer, thisArg, 5); length -= 2; } else { - customizer = typeof thisArg == 'function' ? thisArg : null; + customizer = typeof thisArg == 'function' ? thisArg : undefined; length -= (customizer ? 1 : 0); } if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? null : customizer; + customizer = length < 3 ? undefined : customizer; length = 1; } while (++index < length) { @@ -3226,8 +3156,20 @@ */ 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 + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + 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]); + } var thisBinding = baseCreate(Ctor.prototype), - result = Ctor.apply(thisBinding, arguments); + result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior. // See https://es5.github.io/#x13.2.2 for more details. @@ -3258,32 +3200,24 @@ * Creates a `_.max` or `_.min` function. * * @private - * @param {Function} arrayFunc The function to get the extremum value from an array. - * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum, - * extremum value. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. * @returns {Function} Returns the new extremum function. */ - function createExtremum(arrayFunc, isMin) { + function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = null; } - var func = getCallback(), - noIteratee = iteratee == null; - - if (!(func === baseCallback && noIteratee)) { - noIteratee = false; - iteratee = func(iteratee, thisArg, 3); - } - if (noIteratee) { - var isArr = isArray(collection); - if (!isArr && isString(collection)) { - iteratee = charAtCallback; - } else { - return arrayFunc(isArr ? collection : toIterable(collection)); + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; } } - return extremumBy(collection, iteratee, isMin); + return baseExtremum(collection, iteratee, comparator, exValue); }; } @@ -3346,11 +3280,8 @@ */ function createFlow(fromRight) { return function() { - var length = arguments.length; - if (!length) { - return function() { return arguments[0]; }; - } var wrapper, + length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); @@ -3360,15 +3291,17 @@ if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - var funcName = wrapper ? '' : getFuncName(func); - wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper; + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { + wrapper = new LodashWrapper([]); + } } index = wrapper ? -1 : length; while (++index < length) { func = funcs[index]; - funcName = getFuncName(func); - var data = funcName == 'wrapper' ? getData(func) : null; + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : null; + 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]); } else { @@ -3381,7 +3314,7 @@ return wrapper.plant(args[0]).value(); } var index = 0, - result = funcs[index].apply(this, args); + result = length ? funcs[index].apply(this, args) : args[0]; while (++index < length) { result = funcs[index].call(this, result); @@ -3530,10 +3463,8 @@ isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + Ctor = isBindKey ? null : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -3580,17 +3511,18 @@ return result; } } - var thisBinding = isBind ? thisArg : this; - if (isBindKey) { - func = thisBinding[key]; - } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + if (argPos) { args = reorder(args, argPos); } if (isAry && ary < args.length) { args.length = ary; } - var fn = (this && this !== root && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func; + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } return fn.apply(thisBinding, args); } return wrapper; @@ -3664,10 +3596,10 @@ */ function createSortedIndex(retHighest) { return function(array, value, iteratee, thisArg) { - var func = getCallback(iteratee); - return (func === baseCallback && iteratee == null) + var callback = getCallback(iteratee); + return (iteratee == null && callback === baseCallback) ? binaryIndex(array, value, retHighest) - : binaryIndexBy(array, value, func(iteratee, thisArg, 1), retHighest); + : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); }; } @@ -3753,40 +3685,35 @@ function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { var index = -1, arrLength = array.length, - othLength = other.length, - result = true; + othLength = other.length; if (arrLength != othLength && !(isLoose && othLength > arrLength)) { return false; } - // Deep compare the contents, ignoring non-numeric properties. - while (result && ++index < arrLength) { + // Ignore non-index properties. + while (++index < arrLength) { var arrValue = array[index], - othValue = other[index]; + othValue = other[index], + result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; - result = undefined; - if (customizer) { - result = isLoose - ? customizer(othValue, arrValue, index) - : customizer(arrValue, othValue, index); - } - if (result === undefined) { - // Recursively compare arrays (susceptible to call stack limits). - if (isLoose) { - var othIndex = othLength; - while (othIndex--) { - othValue = other[othIndex]; - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); - if (result) { - break; - } - } - } else { - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + if (result !== undefined) { + if (result) { + continue; } + return false; + } + // Recursively compare arrays (susceptible to call stack limits). + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; } } - return !!result; + return true; } /** @@ -3851,29 +3778,22 @@ if (objLength != othLength && !isLoose) { return false; } - var skipCtor = isLoose, - index = -1; - - while (++index < objLength) { - var key = objProps[index], - result = isLoose ? key in other : hasOwnProperty.call(other, key); - - if (result) { - var objValue = object[key], - othValue = other[key]; - - result = undefined; - if (customizer) { - result = isLoose - ? customizer(othValue, objValue, key) - : customizer(objValue, othValue, key); - } - if (result === undefined) { - // Recursively compare objects (susceptible to call stack limits). - result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB); - } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; } - if (!result) { + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key], + result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; + + // Recursively compare objects (susceptible to call stack limits). + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { return false; } skipCtor || (skipCtor = key == 'constructor'); @@ -3893,34 +3813,6 @@ return true; } - /** - * Gets the extremum value of `collection` invoking `iteratee` for each value - * in `collection` to generate the criterion by which the value is ranked. - * The `iteratee` is invoked with three arguments: (value, index, collection). - * - * @private - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {boolean} [isMin] Specify returning the minimum, instead of the - * maximum, extremum value. - * @returns {*} Returns the extremum value. - */ - function extremumBy(collection, iteratee, isMin) { - var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY, - computed = exValue, - result = computed; - - baseEach(collection, function(value, index, collection) { - var current = iteratee(value, index, collection); - if ((isMin ? (current < computed) : (current > computed)) || - (current === exValue && current === result)) { - computed = current; - result = value; - } - }); - return result; - } - /** * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns @@ -3954,29 +3846,20 @@ * @param {Function} func The function to query. * @returns {string} Returns the function name. */ - var getFuncName = (function() { - if (!support.funcNames) { - return constant(''); - } - if (constant.name == 'constant') { - return baseProperty('name'); - } - return function(func) { - var result = func.name, - array = realNames[result], - length = array ? array.length : 0; + function getFuncName(func) { + var result = func.name, + array = realNames[result], + length = array ? array.length : 0; - while (length--) { - var data = array[length], - otherFunc = data.func; - - if (otherFunc == null || otherFunc == func) { - return data.name; - } + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; } - return result; - }; - }()); + } + return result; + } /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is @@ -4006,15 +3889,34 @@ var getLength = baseProperty('length'); /** - * Creates an array of the own symbols of `object`. + * Gets the propery names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. + * @returns {Array} Returns the match data of `object`. */ - var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) { - return getOwnPropertySymbols(toObject(object)); - }; + function getMatchData(object) { + var result = pairs(object), + length = result.length; + + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } /** * Gets the view, applying any `transforms` to the `start` and `end` positions. @@ -4156,7 +4058,7 @@ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { - value = +value; + value = typeof value == 'number' ? value : parseFloat(value); length = length == null ? MAX_SAFE_INTEGER : length; return value > -1 && value % 1 == 0 && value < length; } @@ -4453,11 +4355,10 @@ function shimKeys(object) { var props = keysIn(object), propsLength = props.length, - length = propsLength && object.length, - support = lodash.support; + length = propsLength && object.length; - var allowIndexes = length && isLength(length) && - (isArray(object) || (support.nonEnumArgs && isArguments(object))); + var allowIndexes = !!length && isLength(length) && + (isArray(object) || isArguments(object)); var index = -1, result = []; @@ -4472,7 +4373,7 @@ } /** - * Converts `value` to an array-like object if it is not one. + * Converts `value` to an array-like object if it's not one. * * @private * @param {*} value The value to process. @@ -4489,7 +4390,7 @@ } /** - * Converts `value` to an object if it is not one. + * Converts `value` to an object if it's not one. * * @private * @param {*} value The value to process. @@ -4500,7 +4401,7 @@ } /** - * Converts `value` to property path array if it is not one. + * Converts `value` to property path array if it's not one. * * @private * @param {*} value The value to process. @@ -5084,27 +4985,19 @@ * _.intersection([1, 2], [4, 2], [2, 1]); * // => [2] */ - function intersection() { - var args = [], - argsIndex = -1, - argsLength = arguments.length, - caches = [], + var intersection = restParam(function(arrays) { + var othLength = arrays.length, + othIndex = othLength, + caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, result = []; - while (++argsIndex < argsLength) { - var value = arguments[argsIndex]; - if (isArrayLike(value)) { - args.push(value); - caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null); - } + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; } - argsLength = args.length; - if (argsLength < 2) { - return result; - } - var array = args[0], + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; @@ -5113,10 +5006,10 @@ while (++index < length) { value = array[index]; if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { - argsIndex = argsLength; - while (--argsIndex) { - var cache = caches[argsIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { continue outer; } } @@ -5127,7 +5020,7 @@ } } return result; - } + }); /** * Gets the last element of `array`. @@ -5710,9 +5603,9 @@ iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; isSorted = false; } - var func = getCallback(); - if (!(func === baseCallback && iteratee == null)) { - iteratee = func(iteratee, thisArg, 3); + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) ? sortedUniq(array, iteratee) @@ -5919,8 +5812,8 @@ */ var zipWith = restParam(function(arrays) { var length = arrays.length, - iteratee = arrays[length - 2], - thisArg = arrays[length - 1]; + iteratee = length > 2 ? arrays[length - 2] : undefined, + thisArg = length > 1 ? arrays[length - 1] : undefined; if (length > 2 && typeof iteratee == 'function') { length -= 2; @@ -6673,7 +6566,7 @@ }); /** - * Invokes the method at `path` on each element in `collection`, returning + * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments * are provided to each invoked method. If `methodName` is a function it is * invoked for, and `this` bound to, each element in `collection`. @@ -6701,7 +6594,7 @@ result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { - var func = isFunc ? path : (isProp && value != null && value[path]); + var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; @@ -6723,7 +6616,7 @@ * callback returns `true` for elements that have the properties of the given * object, else `false`. * - * Many lodash methods are guarded to work as interatees for methods like + * Many lodash methods are guarded to work as iteratees for methods like * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. * * The guarded methods are: @@ -6867,7 +6760,7 @@ * value. The `iteratee` is bound to `thisArg` and invoked with four arguments: * (accumulator, value, index|key, collection). * - * Many lodash methods are guarded to work as interatees for methods like + * Many lodash methods are guarded to work as iteratees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: @@ -7644,12 +7537,13 @@ var curryRight = createCurry(CURRY_RIGHT_FLAG); /** - * Creates a function that delays invoking `func` until after `wait` milliseconds - * have elapsed since the last time it was invoked. The created function comes - * with a `cancel` method to cancel delayed invocations. Provide an options - * object to indicate that `func` should be invoked on the leading and/or - * trailing edge of the `wait` timeout. Subsequent calls to the debounced - * function return the result of the last `func` invocation. + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed invocations. Provide an options object to indicate that `func` + * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * Subsequent calls to the debounced function return the result of the last + * `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the debounced function is @@ -7963,14 +7857,14 @@ } var memoized = function() { var args = arguments, - cache = memoized.cache, - key = resolver ? resolver.apply(this, args) : args[0]; + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; if (cache.has(key)) { return cache.get(key); } var result = func.apply(this, args); - cache.set(key, result); + memoized.cache = cache.set(key, result); return result; }; memoized.cache = new memoize.Cache; @@ -8217,12 +8111,12 @@ } /** - * Creates a function that only invokes `func` at most once per every `wait` - * milliseconds. The created function comes with a `cancel` method to cancel - * delayed invocations. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. - * Subsequent calls to the throttled function return the result of the last - * `func` call. + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed invocations. Provide an options object to indicate + * that `func` should be invoked on the leading and/or trailing edge of the + * `wait` timeout. Subsequent calls to the throttled function return the + * result of the last `func` call. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the throttled function is @@ -8360,8 +8254,9 @@ customizer = isDeep; isDeep = false; } - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); - return baseClone(value, isDeep, customizer); + return typeof customizer == 'function' + ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1)) + : baseClone(value, isDeep); } /** @@ -8410,8 +8305,57 @@ * // => 20 */ function cloneDeep(value, customizer, thisArg) { - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); - return baseClone(value, true, customizer); + return typeof customizer == 'function' + ? baseClone(value, true, bindCallback(customizer, thisArg, 1)) + : baseClone(value, true); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`. + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + function gt(value, other) { + return value > other; + } + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`. + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + function gte(value, other) { + return value >= other; } /** @@ -8574,6 +8518,7 @@ * * @static * @memberOf _ + * @alias eq * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. @@ -8603,12 +8548,9 @@ * // => true */ function isEqual(value, other, customizer, thisArg) { - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); - if (!customizer && isStrictComparable(value) && isStrictComparable(other)) { - return value === other; - } + customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; var result = customizer ? customizer(value, other) : undefined; - return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; } /** @@ -8710,7 +8652,7 @@ // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; - return type == 'function' || (!!value && type == 'object'); + return !!value && (type == 'object' || type == 'function'); } /** @@ -8753,33 +8695,8 @@ * // => true */ function isMatch(object, source, customizer, thisArg) { - var props = keys(source), - length = props.length; - - if (!length) { - return true; - } - if (object == null) { - return false; - } - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); - object = toObject(object); - if (!customizer && length == 1) { - var key = props[0], - value = source[key]; - - if (isStrictComparable(value)) { - return value === object[key] && (value !== undefined || (key in object)); - } - } - var values = Array(length), - strictCompareFlags = Array(length); - - while (length--) { - value = values[length] = source[props[length]]; - strictCompareFlags[length] = isStrictComparable(value); - } - return baseIsMatch(object, props, values, strictCompareFlags, customizer); + customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); } /** @@ -8919,8 +8836,8 @@ if (!(value && objToString.call(value) == objectTag)) { return false; } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + var valueOf = getNative(value, 'valueOf'), + objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) @@ -9007,6 +8924,54 @@ return value === undefined; } + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`. + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + function lt(value, other) { + return value < other; + } + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`. + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + function lte(value, other) { + return value <= other; + } + /** * Converts `value` to an array. * @@ -9399,7 +9364,7 @@ } /** - * Gets the property value of `path` on `object`. If the resolved value is + * Gets the property value at `path` of `object`. If the resolved value is * `undefined` the `defaultValue` is used in its place. * * @static @@ -9457,10 +9422,14 @@ if (!result && !isKey(path)) { path = toPath(path); object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } path = last(path); - result = object != null && hasOwnProperty.call(object, path); + result = hasOwnProperty.call(object, path); } - return result; + return result || (isLength(object.length) && isIndex(path, object.length) && + (isArray(object) || isArguments(object))); } /** @@ -9541,7 +9510,7 @@ * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object != null && object.constructor; + var Ctor = object == null ? null : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); @@ -9580,7 +9549,7 @@ } var length = object.length; length = (length && isLength(length) && - (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0; + (isArray(object) || isArguments(object)) && length) || 0; var Ctor = object.constructor, index = -1, @@ -9767,6 +9736,8 @@ * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, @@ -9943,7 +9914,7 @@ if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); } } else { accumulator = {}; @@ -10218,7 +10189,7 @@ * use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like - * ">" and "/" don't require escaping in HTML and have no special meaning + * ">" and "/" don't need escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. @@ -10295,7 +10266,7 @@ }); /** - * Pads `string` on the left and right sides if it is shorter than `length`. + * Pads `string` on the left and right sides if it's shorter than `length`. * Padding characters are truncated if they can't be evenly divided by `length`. * * @static @@ -10333,7 +10304,7 @@ } /** - * Pads `string` on the left side if it is shorter than `length`. Padding + * Pads `string` on the left side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static @@ -10357,7 +10328,7 @@ var padLeft = createPadDir(); /** - * Pads `string` on the right side if it is shorter than `length`. Padding + * Pads `string` on the right side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static @@ -10838,7 +10809,7 @@ } /** - * Truncates `string` if it is longer than the given maximum string length. + * Truncates `string` if it's longer than the given maximum string length. * The last characters of the truncated string are replaced with the omission * string which defaults to "...". * @@ -11137,7 +11108,7 @@ * @memberOf _ * @category Utility * @param {Array|string} path The path of the property to get. - * @param {*} value The value to compare. + * @param {*} srcValue The value to match. * @returns {Function} Returns the new function. * @example * @@ -11149,8 +11120,8 @@ * _.find(users, _.matchesProperty('user', 'fred')); * // => { 'user': 'fred' } */ - function matchesProperty(path, value) { - return baseMatchesProperty(path, baseClone(value, true)); + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); } /** @@ -11231,9 +11202,6 @@ * }); * } * - * // use `_.runInContext` to avoid conflicts (esp. in Node.js) - * var _ = require('lodash').runInContext(); - * * _.mixin({ 'vowels': vowels }); * _.vowels('fred'); * // => ['e'] @@ -11248,8 +11216,8 @@ function mixin(object, source, options) { if (options == null) { var isObj = isObject(source), - props = isObj && keys(source), - methodNames = props && props.length && baseFunctions(source, props); + props = isObj ? keys(source) : null, + methodNames = (props && props.length) ? baseFunctions(source, props) : null; if (!(methodNames ? methodNames.length : isObj)) { methodNames = false; @@ -11579,7 +11547,7 @@ * _.max(users, 'age'); * // => { 'user': 'fred', 'age': 40 } */ - var max = createExtremum(arrayMax); + var max = createExtremum(gt, -Infinity); /** * Gets the minimum value of `collection`. If `collection` is empty or falsey @@ -11628,7 +11596,7 @@ * _.min(users, 'age'); * // => { 'user': 'barney', 'age': 36 } */ - var min = createExtremum(arrayMin, true); + var min = createExtremum(lt, Infinity); /** * Gets the sum of the values in `collection`. @@ -11666,12 +11634,12 @@ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = null; } - var func = getCallback(), + var callback = getCallback(), noIteratee = iteratee == null; - if (!(func === baseCallback && noIteratee)) { + if (!(noIteratee && callback === baseCallback)) { noIteratee = false; - iteratee = func(iteratee, thisArg, 3); + iteratee = callback(iteratee, thisArg, 3); } return noIteratee ? arraySum(isArray(collection) ? collection : toIterable(collection)) @@ -11846,6 +11814,8 @@ lodash.findWhere = findWhere; lodash.first = first; lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; lodash.has = has; lodash.identity = identity; lodash.includes = includes; @@ -11875,6 +11845,8 @@ lodash.kebabCase = kebabCase; lodash.last = last; lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; lodash.max = max; lodash.min = min; lodash.noConflict = noConflict; @@ -11911,6 +11883,7 @@ lodash.all = every; lodash.any = some; lodash.contains = includes; + lodash.eq = isEqual; lodash.detect = find; lodash.foldl = reduce; lodash.foldr = reduceRight; @@ -12190,7 +12163,7 @@ if (moduleExports) { (freeModule.exports = _)._ = _; } - // Export for Narwhal or Rhino -require. + // Export for Rhino with CommonJS support. else { freeExports._ = _; } diff --git a/internal/SetCache.js b/internal/SetCache.js index ed3dc6b0f..b6e1a3ec9 100644 --- a/internal/SetCache.js +++ b/internal/SetCache.js @@ -1,11 +1,11 @@ var cachePush = require('./cachePush'), - isNative = require('../lang/isNative'); + getNative = require('./getNative'); /** Native method references. */ -var Set = isNative(Set = global.Set) && Set; +var Set = getNative(root, 'Set'); /* Native method references for those with the same name as other `lodash` methods. */ -var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; +var nativeCreate = getNative(Object, 'create'); /** * diff --git a/internal/arrayExtremum.js b/internal/arrayExtremum.js new file mode 100644 index 000000000..c56969e7a --- /dev/null +++ b/internal/arrayExtremum.js @@ -0,0 +1,30 @@ +/** + * A specialized version of `baseExtremum` for arrays whichs invokes `iteratee` + * with one argument: (value). + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. + * @returns {*} Returns the extremum value. + */ +function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, + length = array.length, + computed = exValue, + result = computed; + + while (++index < length) { + var value = array[index], + current = +iteratee(value); + + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; +} + +module.exports = arrayExtremum; diff --git a/internal/arrayMax.js b/internal/arrayMax.js deleted file mode 100644 index 3f62469f9..000000000 --- a/internal/arrayMax.js +++ /dev/null @@ -1,25 +0,0 @@ -/** Used as references for `-Infinity` and `Infinity`. */ -var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY; - -/** - * A specialized version of `_.max` for arrays without support for iteratees. - * - * @private - * @param {Array} array The array to iterate over. - * @returns {*} Returns the maximum value. - */ -function arrayMax(array) { - var index = -1, - length = array.length, - result = NEGATIVE_INFINITY; - - while (++index < length) { - var value = array[index]; - if (value > result) { - result = value; - } - } - return result; -} - -module.exports = arrayMax; diff --git a/internal/arrayMin.js b/internal/arrayMin.js deleted file mode 100644 index dd1f175ce..000000000 --- a/internal/arrayMin.js +++ /dev/null @@ -1,25 +0,0 @@ -/** Used as references for `-Infinity` and `Infinity`. */ -var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; - -/** - * A specialized version of `_.min` for arrays without support for iteratees. - * - * @private - * @param {Array} array The array to iterate over. - * @returns {*} Returns the minimum value. - */ -function arrayMin(array) { - var index = -1, - length = array.length, - result = POSITIVE_INFINITY; - - while (++index < length) { - var value = array[index]; - if (value < result) { - result = value; - } - } - return result; -} - -module.exports = arrayMin; diff --git a/internal/assignWith.js b/internal/assignWith.js index c5a629d02..d2b261ad2 100644 --- a/internal/assignWith.js +++ b/internal/assignWith.js @@ -1,11 +1,4 @@ -var getSymbols = require('./getSymbols'), - keys = require('../object/keys'); - -/** Used for native method references. */ -var arrayProto = Array.prototype; - -/** Native method references. */ -var push = arrayProto.push; +var keys = require('../object/keys'); /** * A specialized version of `_.assign` for customizing assigned values without @@ -19,10 +12,8 @@ var push = arrayProto.push; * @returns {Object} Returns `object`. */ function assignWith(object, source, customizer) { - var props = keys(source); - push.apply(props, getSymbols(source)); - var index = -1, + props = keys(source), length = props.length; while (++index < length) { diff --git a/internal/baseAssign.js b/internal/baseAssign.js index c290fe95e..cfad6e0c3 100644 --- a/internal/baseAssign.js +++ b/internal/baseAssign.js @@ -1,34 +1,6 @@ var baseCopy = require('./baseCopy'), - getSymbols = require('./getSymbols'), - isNative = require('../lang/isNative'), keys = require('../object/keys'); -/** Native method references. */ -var preventExtensions = isNative(preventExtensions = Object.preventExtensions) && preventExtensions; - -/** Used as `baseAssign`. */ -var nativeAssign = (function() { - // Avoid `Object.assign` in Firefox 34-37 which have an early implementation - // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344 - // for more details. - // - // Use `Object.preventExtensions` on a plain object instead of simply using - // `Object('x')` because Chrome and IE fail to throw an error when attempting - // to assign values to readonly indexes of strings. - var func = preventExtensions && isNative(func = Object.assign) && func; - try { - if (func) { - var object = preventExtensions({ '1': 0 }); - object[0] = 1; - } - } catch(e) { - // Only attempt in strict mode. - try { func(object, 'xo'); } catch(e) {} - return !object[1] && func; - } - return false; -}()); - /** * The base implementation of `_.assign` without support for argument juggling, * multiple sources, and `customizer` functions. @@ -38,10 +10,10 @@ var nativeAssign = (function() { * @param {Object} source The source object. * @returns {Object} Returns `object`. */ -var baseAssign = nativeAssign || function(object, source) { +function baseAssign(object, source) { return source == null ? object - : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object)); -}; + : baseCopy(source, keys(source), object); +} module.exports = baseAssign; diff --git a/internal/baseAt.js b/internal/baseAt.js index b90aa4cc4..bbafd1d5a 100644 --- a/internal/baseAt.js +++ b/internal/baseAt.js @@ -14,7 +14,7 @@ function baseAt(collection, props) { var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), - length = isArr && collection.length, + length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); diff --git a/internal/baseCompareAscending.js b/internal/baseCompareAscending.js index f2b7657fb..c8259c72d 100644 --- a/internal/baseCompareAscending.js +++ b/internal/baseCompareAscending.js @@ -3,19 +3,28 @@ * sorts them in ascending order without guaranteeing a stable sort. * * @private - * @param {*} value The value to compare to `other`. - * @param {*} other The value to compare to `value`. + * @param {*} value The value to compare. + * @param {*} other The other value to compare. * @returns {number} Returns the sort order indicator for `value`. */ function baseCompareAscending(value, other) { if (value !== other) { - var valIsReflexive = value === value, + var valIsNull = value === null, + valIsUndef = value === undefined, + valIsReflexive = value === value; + + var othIsNull = other === null, + othIsUndef = other === undefined, othIsReflexive = other === other; - if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) { + if ((value > other && !othIsNull) || !valIsReflexive || + (valIsNull && !othIsUndef && othIsReflexive) || + (valIsUndef && othIsReflexive)) { return 1; } - if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) { + if ((value < other && !valIsNull) || !othIsReflexive || + (othIsNull && !valIsUndef && valIsReflexive) || + (othIsUndef && valIsReflexive)) { return -1; } } diff --git a/internal/baseCreate.js b/internal/baseCreate.js index da6725f6a..8f36becd3 100644 --- a/internal/baseCreate.js +++ b/internal/baseCreate.js @@ -9,14 +9,14 @@ var isObject = require('../lang/isObject'); * @returns {Object} Returns the new object. */ var baseCreate = (function() { - function Object() {} + function object() {} return function(prototype) { if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; + object.prototype = prototype; + var result = new object; + object.prototype = null; } - return result || global.Object(); + return result || {}; }; }()); diff --git a/internal/extremumBy.js b/internal/baseExtremum.js similarity index 50% rename from internal/extremumBy.js rename to internal/baseExtremum.js index ddbfe0ca4..b0efff6f9 100644 --- a/internal/extremumBy.js +++ b/internal/baseExtremum.js @@ -1,30 +1,24 @@ var baseEach = require('./baseEach'); -/** Used as references for `-Infinity` and `Infinity`. */ -var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, - POSITIVE_INFINITY = Number.POSITIVE_INFINITY; - /** * Gets the extremum value of `collection` invoking `iteratee` for each value * in `collection` to generate the criterion by which the value is ranked. - * The `iteratee` is invoked with three arguments: (value, index, collection). + * The `iteratee` is invoked with three arguments: (value, index|key, collection). * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. - * @param {boolean} [isMin] Specify returning the minimum, instead of the - * maximum, extremum value. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. * @returns {*} Returns the extremum value. */ -function extremumBy(collection, iteratee, isMin) { - var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY, - computed = exValue, +function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; baseEach(collection, function(value, index, collection) { - var current = iteratee(value, index, collection); - if ((isMin ? (current < computed) : (current > computed)) || - (current === exValue && current === result)) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || (current === exValue && current === result)) { computed = current; result = value; } @@ -32,4 +26,4 @@ function extremumBy(collection, iteratee, isMin) { return result; } -module.exports = extremumBy; +module.exports = baseExtremum; diff --git a/internal/baseGet.js b/internal/baseGet.js index 5a9b48c71..ad9b1ee11 100644 --- a/internal/baseGet.js +++ b/internal/baseGet.js @@ -17,11 +17,11 @@ function baseGet(object, path, pathKey) { if (pathKey !== undefined && pathKey in toObject(object)) { path = [pathKey]; } - var index = -1, + var index = 0, length = path.length; - while (object != null && ++index < length) { - object = object[path[index]]; + while (object != null && index < length) { + object = object[path[index++]]; } return (index && index == length) ? object : undefined; } diff --git a/internal/baseIsEqual.js b/internal/baseIsEqual.js index ca4e8e907..932dec7b7 100644 --- a/internal/baseIsEqual.js +++ b/internal/baseIsEqual.js @@ -1,4 +1,5 @@ -var baseIsEqualDeep = require('./baseIsEqualDeep'); +var baseIsEqualDeep = require('./baseIsEqualDeep'), + isObject = require('../lang/isObject'); /** * The base implementation of `_.isEqual` without support for `this` binding @@ -14,17 +15,10 @@ var baseIsEqualDeep = require('./baseIsEqualDeep'); * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { - // Exit early for identical values. if (value === other) { return true; } - var valType = typeof value, - othType = typeof other; - - // Exit early for unlike primitive values. - if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') || - value == null || other == null) { - // Return `false` unless both values are `NaN`. + if (value == null || other == null || (!isObject(value) && !isObject(other))) { return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); diff --git a/internal/baseIsEqualDeep.js b/internal/baseIsEqualDeep.js index e6829a931..586ebcd1c 100644 --- a/internal/baseIsEqualDeep.js +++ b/internal/baseIsEqualDeep.js @@ -66,11 +66,11 @@ function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, return equalByTag(object, other, objTag); } if (!isLoose) { - var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), - othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - if (valWrapped || othWrapped) { - return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); } } if (!isSameTag) { diff --git a/internal/baseIsMatch.js b/internal/baseIsMatch.js index 5c9fb3a68..ea48bb656 100644 --- a/internal/baseIsMatch.js +++ b/internal/baseIsMatch.js @@ -1,4 +1,5 @@ -var baseIsEqual = require('./baseIsEqual'); +var baseIsEqual = require('./baseIsEqual'), + toObject = require('./toObject'); /** * The base implementation of `_.isMatch` without support for callback @@ -6,41 +7,43 @@ var baseIsEqual = require('./baseIsEqual'); * * @private * @param {Object} object The object to inspect. - * @param {Array} props The source property names to match. - * @param {Array} values The source values to match. - * @param {Array} strictCompareFlags Strict comparison flags for source values. + * @param {Array} matchData The propery names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparing objects. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ -function baseIsMatch(object, props, values, strictCompareFlags, customizer) { - var index = -1, - length = props.length, +function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, + length = index, noCustomizer = !customizer; - while (++index < length) { - if ((noCustomizer && strictCompareFlags[index]) - ? values[index] !== object[props[index]] - : !(props[index] in object) + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) ) { return false; } } - index = -1; while (++index < length) { - var key = props[index], + data = matchData[index]; + var key = data[0], objValue = object[key], - srcValue = values[index]; + srcValue = data[1]; - if (noCustomizer && strictCompareFlags[index]) { - var result = objValue !== undefined || (key in object); - } else { - result = customizer ? customizer(objValue, srcValue, key) : undefined; - if (result === undefined) { - result = baseIsEqual(srcValue, objValue, customizer, true); + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; } - } - if (!result) { - return false; } } return true; diff --git a/internal/baseMatches.js b/internal/baseMatches.js index 885e9f791..5f76c67dc 100644 --- a/internal/baseMatches.js +++ b/internal/baseMatches.js @@ -1,7 +1,5 @@ var baseIsMatch = require('./baseIsMatch'), - constant = require('../utility/constant'), - isStrictComparable = require('./isStrictComparable'), - keys = require('../object/keys'), + getMatchData = require('./getMatchData'), toObject = require('./toObject'); /** @@ -12,35 +10,20 @@ var baseIsMatch = require('./baseIsMatch'), * @returns {Function} Returns the new function. */ function baseMatches(source) { - var props = keys(source), - length = props.length; + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], + value = matchData[0][1]; - if (!length) { - return constant(true); - } - if (length == 1) { - var key = props[0], - value = source[key]; - - if (isStrictComparable(value)) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === value && (value !== undefined || (key in toObject(object))); - }; - } - } - var values = Array(length), - strictCompareFlags = Array(length); - - while (length--) { - value = source[props[length]]; - values[length] = value; - strictCompareFlags[length] = isStrictComparable(value); + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || (key in toObject(object))); + }; } return function(object) { - return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags); + return baseIsMatch(object, matchData); }; } diff --git a/internal/baseMatchesProperty.js b/internal/baseMatchesProperty.js index 1bbd3464d..12229714d 100644 --- a/internal/baseMatchesProperty.js +++ b/internal/baseMatchesProperty.js @@ -14,12 +14,12 @@ var baseGet = require('./baseGet'), * * @private * @param {string} path The path of the property to get. - * @param {*} value The value to compare. + * @param {*} srcValue The value to compare. * @returns {Function} Returns the new function. */ -function baseMatchesProperty(path, value) { +function baseMatchesProperty(path, srcValue) { var isArr = isArray(path), - isCommon = isKey(path) && isStrictComparable(value), + isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = (path + ''); path = toPath(path); @@ -37,9 +37,9 @@ function baseMatchesProperty(path, value) { key = last(path); object = toObject(object); } - return object[key] === value - ? (value !== undefined || (key in object)) - : baseIsEqual(value, object[key], null, true); + return object[key] === srcValue + ? (srcValue !== undefined || (key in object)) + : baseIsEqual(srcValue, object[key], undefined, true); }; } diff --git a/internal/baseMerge.js b/internal/baseMerge.js index c76c21029..28a871069 100644 --- a/internal/baseMerge.js +++ b/internal/baseMerge.js @@ -1,6 +1,5 @@ var arrayEach = require('./arrayEach'), baseMergeDeep = require('./baseMergeDeep'), - getSymbols = require('./getSymbols'), isArray = require('../lang/isArray'), isArrayLike = require('./isArrayLike'), isObject = require('../lang/isObject'), @@ -8,12 +7,6 @@ var arrayEach = require('./arrayEach'), isTypedArray = require('../lang/isTypedArray'), keys = require('../object/keys'); -/** Used for native method references. */ -var arrayProto = Array.prototype; - -/** Native method references. */ -var push = arrayProto.push; - /** * The base implementation of `_.merge` without support for argument juggling, * multiple sources, and `this` binding `customizer` functions. @@ -30,11 +23,9 @@ function baseMerge(object, source, customizer, stackA, stackB) { if (!isObject(object)) { return object; } - var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)); - if (!isSrcArr) { - var props = keys(source); - push.apply(props, getSymbols(source)); - } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), + props = isSrcArr ? null : keys(source); + arrayEach(props || source, function(srcValue, key) { if (props) { key = srcValue; @@ -53,7 +44,7 @@ function baseMerge(object, source, customizer, stackA, stackB) { if (isCommon) { result = srcValue; } - if ((isSrcArr || result !== undefined) && + if ((result !== undefined || (isSrcArr && !(key in object))) && (isCommon || (result === result ? (result !== value) : (value === value)))) { object[key] = result; } diff --git a/internal/basePullAt.js b/internal/basePullAt.js index 41f9700bf..6c4ff8420 100644 --- a/internal/basePullAt.js +++ b/internal/basePullAt.js @@ -18,7 +18,7 @@ var splice = arrayProto.splice; function basePullAt(array, indexes) { var length = array ? indexes.length : 0; while (length--) { - var index = parseFloat(indexes[length]); + var index = indexes[length]; if (index != previous && isIndex(index)) { var previous = index; splice.call(array, index, 1); diff --git a/internal/baseToString.js b/internal/baseToString.js index 3b0d0eca9..4de76a7ee 100644 --- a/internal/baseToString.js +++ b/internal/baseToString.js @@ -1,5 +1,5 @@ /** - * Converts `value` to a string if it is not one. An empty string is returned + * Converts `value` to a string if it's not one. An empty string is returned * for `null` or `undefined` values. * * @private diff --git a/internal/binaryIndex.js b/internal/binaryIndex.js index cd5a072d3..af419a26f 100644 --- a/internal/binaryIndex.js +++ b/internal/binaryIndex.js @@ -2,7 +2,7 @@ var binaryIndexBy = require('./binaryIndexBy'), identity = require('../utility/identity'); /** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, +var MAX_ARRAY_LENGTH = 4294967295, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** @@ -25,7 +25,7 @@ function binaryIndex(array, value, retHighest) { var mid = (low + high) >>> 1, computed = array[mid]; - if (retHighest ? (computed <= value) : (computed < value)) { + if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { low = mid + 1; } else { high = mid; diff --git a/internal/binaryIndexBy.js b/internal/binaryIndexBy.js index 04cb43e7b..5bcd7a744 100644 --- a/internal/binaryIndexBy.js +++ b/internal/binaryIndexBy.js @@ -5,7 +5,7 @@ var floor = Math.floor; var nativeMin = Math.min; /** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, +var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; /** @@ -27,17 +27,23 @@ function binaryIndexBy(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, + valIsNull = value === null, valIsUndef = value === undefined; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), + isDef = computed !== undefined, isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); } else if (valIsUndef) { - setLow = isReflexive && (retHighest || computed !== undefined); + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); } diff --git a/internal/bufferClone.js b/internal/bufferClone.js index 40322e19f..fe8ca944a 100644 --- a/internal/bufferClone.js +++ b/internal/bufferClone.js @@ -1,11 +1,11 @@ var constant = require('../utility/constant'), - isNative = require('../lang/isNative'); + getNative = require('./getNative'); /** Native method references. */ -var ArrayBuffer = isNative(ArrayBuffer = global.ArrayBuffer) && ArrayBuffer, - bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, +var ArrayBuffer = getNative(root, 'ArrayBuffer'), + bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), floor = Math.floor, - Uint8Array = isNative(Uint8Array = global.Uint8Array) && Uint8Array; + Uint8Array = getNative(root, 'Uint8Array'); /** Used to clone array buffers. */ var Float64Array = (function() { @@ -13,10 +13,10 @@ var Float64Array = (function() { // where the array buffer's `byteLength` is not a multiple of the typed // array's `BYTES_PER_ELEMENT`. try { - var func = isNative(func = global.Float64Array) && func, + var func = getNative(root, 'Float64Array'), result = new func(new ArrayBuffer(10), 0, 1) && func; } catch(e) {} - return result; + return result || null; }()); /** Used as the size, in bytes, of each `Float64Array` element. */ diff --git a/internal/charAtCallback.js b/internal/charAtCallback.js deleted file mode 100644 index fbc3a9195..000000000 --- a/internal/charAtCallback.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Used by `_.max` and `_.min` as the default callback for string values. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the code unit of the first character of the string. - */ -function charAtCallback(string) { - return string.charCodeAt(0); -} - -module.exports = charAtCallback; diff --git a/internal/createAssigner.js b/internal/createAssigner.js index 43593f06d..e06c1b1b7 100644 --- a/internal/createAssigner.js +++ b/internal/createAssigner.js @@ -16,19 +16,19 @@ function createAssigner(assigner) { return restParam(function(object, sources) { var index = -1, length = object == null ? 0 : sources.length, - customizer = length > 2 && sources[length - 2], - guard = length > 2 && sources[2], - thisArg = length > 1 && sources[length - 1]; + customizer = length > 2 ? sources[length - 2] : undefined, + guard = length > 2 ? sources[2] : undefined, + thisArg = length > 1 ? sources[length - 1] : undefined; if (typeof customizer == 'function') { customizer = bindCallback(customizer, thisArg, 5); length -= 2; } else { - customizer = typeof thisArg == 'function' ? thisArg : null; + customizer = typeof thisArg == 'function' ? thisArg : undefined; length -= (customizer ? 1 : 0); } if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? null : customizer; + customizer = length < 3 ? undefined : customizer; length = 1; } while (++index < length) { diff --git a/internal/createCache.js b/internal/createCache.js index e12d9fd79..cfe3e5473 100644 --- a/internal/createCache.js +++ b/internal/createCache.js @@ -1,12 +1,12 @@ var SetCache = require('./SetCache'), constant = require('../utility/constant'), - isNative = require('../lang/isNative'); + getNative = require('./getNative'); /** Native method references. */ -var Set = isNative(Set = global.Set) && Set; +var Set = getNative(root, 'Set'); /* Native method references for those with the same name as other `lodash` methods. */ -var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; +var nativeCreate = getNative(Object, 'create'); /** * Creates a `Set` cache object to optimize linear searches of large arrays. diff --git a/internal/createCtorWrapper.js b/internal/createCtorWrapper.js index 31bec3d5f..f1a12d14e 100644 --- a/internal/createCtorWrapper.js +++ b/internal/createCtorWrapper.js @@ -11,8 +11,20 @@ var baseCreate = require('./baseCreate'), */ 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 + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + 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]); + } var thisBinding = baseCreate(Ctor.prototype), - result = Ctor.apply(thisBinding, arguments); + result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior. // See https://es5.github.io/#x13.2.2 for more details. diff --git a/internal/createExtremum.js b/internal/createExtremum.js index 4d05d2e89..60f0b7919 100644 --- a/internal/createExtremum.js +++ b/internal/createExtremum.js @@ -1,37 +1,31 @@ -var baseCallback = require('./baseCallback'), - charAtCallback = require('./charAtCallback'), - extremumBy = require('./extremumBy'), - isArray = require('../lang/isArray'), +var arrayExtremum = require('./arrayExtremum'), + baseCallback = require('./baseCallback'), + baseExtremum = require('./baseExtremum'), isIterateeCall = require('./isIterateeCall'), - isString = require('../lang/isString'), toIterable = require('./toIterable'); /** * Creates a `_.max` or `_.min` function. * * @private - * @param {Function} arrayFunc The function to get the extremum value from an array. - * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum, - * extremum value. + * @param {Function} comparator The function used to compare values. + * @param {*} exValue The initial extremum value. * @returns {Function} Returns the new extremum function. */ -function createExtremum(arrayFunc, isMin) { +function createExtremum(comparator, exValue) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = null; } - var noIteratee = iteratee == null; - - iteratee = noIteratee ? iteratee : baseCallback(iteratee, thisArg, 3); - if (noIteratee) { - var isArr = isArray(collection); - if (!isArr && isString(collection)) { - iteratee = charAtCallback; - } else { - return arrayFunc(isArr ? collection : toIterable(collection)); + iteratee = baseCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; } } - return extremumBy(collection, iteratee, isMin); + return baseExtremum(collection, iteratee, comparator, exValue); }; } diff --git a/internal/createFlow.js b/internal/createFlow.js index 6fe12b2c6..f1821835f 100644 --- a/internal/createFlow.js +++ b/internal/createFlow.js @@ -22,11 +22,8 @@ var FUNC_ERROR_TEXT = 'Expected a function'; */ function createFlow(fromRight) { return function() { - var length = arguments.length; - if (!length) { - return function() { return arguments[0]; }; - } var wrapper, + length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); @@ -36,15 +33,17 @@ function createFlow(fromRight) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - var funcName = wrapper ? '' : getFuncName(func); - wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper; + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { + wrapper = new LodashWrapper([]); + } } index = wrapper ? -1 : length; while (++index < length) { func = funcs[index]; - funcName = getFuncName(func); - var data = funcName == 'wrapper' ? getData(func) : null; + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : null; + 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]); } else { @@ -57,7 +56,7 @@ function createFlow(fromRight) { return wrapper.plant(args[0]).value(); } var index = 0, - result = funcs[index].apply(this, args); + result = length ? funcs[index].apply(this, args) : args[0]; while (++index < length) { result = funcs[index].call(this, result); diff --git a/internal/createHybridWrapper.js b/internal/createHybridWrapper.js index fb62371bf..d7de9ade7 100644 --- a/internal/createHybridWrapper.js +++ b/internal/createHybridWrapper.js @@ -43,10 +43,8 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, - isCurryRight = bitmask & CURRY_RIGHT_FLAG; - - var Ctor = !isBindKey && createCtorWrapper(func), - key = func; + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + Ctor = isBindKey ? null : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by @@ -93,17 +91,18 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials return result; } } - var thisBinding = isBind ? thisArg : this; - if (isBindKey) { - func = thisBinding[key]; - } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + if (argPos) { args = reorder(args, argPos); } if (isAry && ary < args.length) { args.length = ary; } - var fn = (this && this !== global && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func; + if (this && this !== global && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } return fn.apply(thisBinding, args); } return wrapper; diff --git a/internal/equalArrays.js b/internal/equalArrays.js index 0b032ac6a..e0bb2d32a 100644 --- a/internal/equalArrays.js +++ b/internal/equalArrays.js @@ -1,3 +1,5 @@ +var arraySome = require('./arraySome'); + /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. @@ -15,40 +17,35 @@ function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { var index = -1, arrLength = array.length, - othLength = other.length, - result = true; + othLength = other.length; if (arrLength != othLength && !(isLoose && othLength > arrLength)) { return false; } - // Deep compare the contents, ignoring non-numeric properties. - while (result && ++index < arrLength) { + // Ignore non-index properties. + while (++index < arrLength) { var arrValue = array[index], - othValue = other[index]; + othValue = other[index], + result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; - result = undefined; - if (customizer) { - result = isLoose - ? customizer(othValue, arrValue, index) - : customizer(arrValue, othValue, index); - } - if (result === undefined) { - // Recursively compare arrays (susceptible to call stack limits). - if (isLoose) { - var othIndex = othLength; - while (othIndex--) { - othValue = other[othIndex]; - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); - if (result) { - break; - } - } - } else { - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + if (result !== undefined) { + if (result) { + continue; } + return false; + } + // Recursively compare arrays (susceptible to call stack limits). + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; } } - return !!result; + return true; } module.exports = equalArrays; diff --git a/internal/equalObjects.js b/internal/equalObjects.js index 5ea4ec5b8..1297a3b2a 100644 --- a/internal/equalObjects.js +++ b/internal/equalObjects.js @@ -29,29 +29,22 @@ function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, sta if (objLength != othLength && !isLoose) { return false; } - var skipCtor = isLoose, - index = -1; - - while (++index < objLength) { - var key = objProps[index], - result = isLoose ? key in other : hasOwnProperty.call(other, key); - - if (result) { - var objValue = object[key], - othValue = other[key]; - - result = undefined; - if (customizer) { - result = isLoose - ? customizer(othValue, objValue, key) - : customizer(objValue, othValue, key); - } - if (result === undefined) { - // Recursively compare objects (susceptible to call stack limits). - result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB); - } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; } - if (!result) { + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key], + result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; + + // Recursively compare objects (susceptible to call stack limits). + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { return false; } skipCtor || (skipCtor = key == 'constructor'); diff --git a/internal/getFuncName.js b/internal/getFuncName.js index 3102b7142..2ea73a6cd 100644 --- a/internal/getFuncName.js +++ b/internal/getFuncName.js @@ -1,7 +1,4 @@ -var baseProperty = require('./baseProperty'), - constant = require('../utility/constant'), - realNames = require('./realNames'), - support = require('../support'); +var realNames = require('./realNames'); /** * Gets the name of `func`. @@ -10,28 +7,19 @@ var baseProperty = require('./baseProperty'), * @param {Function} func The function to query. * @returns {string} Returns the function name. */ -var getFuncName = (function() { - if (!support.funcNames) { - return constant(''); - } - if (constant.name == 'constant') { - return baseProperty('name'); - } - return function(func) { - var result = func.name, - array = realNames[result], - length = array ? array.length : 0; +function getFuncName(func) { + var result = func.name, + array = realNames[result], + length = array ? array.length : 0; - while (length--) { - var data = array[length], - otherFunc = data.func; - - if (otherFunc == null || otherFunc == func) { - return data.name; - } + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; } - return result; - }; -}()); + } + return result; +} module.exports = getFuncName; diff --git a/internal/getMatchData.js b/internal/getMatchData.js new file mode 100644 index 000000000..6d235b916 --- /dev/null +++ b/internal/getMatchData.js @@ -0,0 +1,21 @@ +var isStrictComparable = require('./isStrictComparable'), + pairs = require('../object/pairs'); + +/** + * Gets the propery names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ +function getMatchData(object) { + var result = pairs(object), + length = result.length; + + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; +} + +module.exports = getMatchData; diff --git a/internal/getNative.js b/internal/getNative.js new file mode 100644 index 000000000..bceb317fd --- /dev/null +++ b/internal/getNative.js @@ -0,0 +1,16 @@ +var isNative = require('../lang/isNative'); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +module.exports = getNative; diff --git a/internal/getSymbols.js b/internal/getSymbols.js deleted file mode 100644 index e6a4d2991..000000000 --- a/internal/getSymbols.js +++ /dev/null @@ -1,19 +0,0 @@ -var constant = require('../utility/constant'), - isNative = require('../lang/isNative'), - toObject = require('./toObject'); - -/** Native method references. */ -var getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols; - -/** - * Creates an array of the own symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. - */ -var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) { - return getOwnPropertySymbols(toObject(object)); -}; - -module.exports = getSymbols; diff --git a/internal/isIndex.js b/internal/isIndex.js index caa2b94b1..e5b94f5c8 100644 --- a/internal/isIndex.js +++ b/internal/isIndex.js @@ -2,7 +2,7 @@ * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * of an array-like value. */ -var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; +var MAX_SAFE_INTEGER = 9007199254740991; /** * Checks if `value` is a valid array-like index. @@ -13,7 +13,7 @@ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { - value = +value; + value = typeof value == 'number' ? value : parseFloat(value); length = length == null ? MAX_SAFE_INTEGER : length; return value > -1 && value % 1 == 0 && value < length; } diff --git a/internal/isLength.js b/internal/isLength.js index 1e3f11c10..39c85022f 100644 --- a/internal/isLength.js +++ b/internal/isLength.js @@ -2,7 +2,7 @@ * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * of an array-like value. */ -var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; +var MAX_SAFE_INTEGER = 9007199254740991; /** * Checks if `value` is a valid array-like length. diff --git a/internal/metaMap.js b/internal/metaMap.js index 3573837fd..017577494 100644 --- a/internal/metaMap.js +++ b/internal/metaMap.js @@ -1,7 +1,7 @@ -var isNative = require('../lang/isNative'); +var getNative = require('./getNative'); /** Native method references. */ -var WeakMap = isNative(WeakMap = global.WeakMap) && WeakMap; +var WeakMap = getNative(root, 'WeakMap'); /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; diff --git a/internal/shimKeys.js b/internal/shimKeys.js index d165c40cb..189e492b7 100644 --- a/internal/shimKeys.js +++ b/internal/shimKeys.js @@ -2,8 +2,7 @@ var isArguments = require('../lang/isArguments'), isArray = require('../lang/isArray'), isIndex = require('./isIndex'), isLength = require('./isLength'), - keysIn = require('../object/keysIn'), - support = require('../support'); + keysIn = require('../object/keysIn'); /** Used for native method references. */ var objectProto = Object.prototype; @@ -24,8 +23,8 @@ function shimKeys(object) { propsLength = props.length, length = propsLength && object.length; - var allowIndexes = length && isLength(length) && - (isArray(object) || (support.nonEnumArgs && isArguments(object))); + var allowIndexes = !!length && isLength(length) && + (isArray(object) || isArguments(object)); var index = -1, result = []; diff --git a/internal/toIterable.js b/internal/toIterable.js index ae63a33be..c0a5b2885 100644 --- a/internal/toIterable.js +++ b/internal/toIterable.js @@ -3,7 +3,7 @@ var isArrayLike = require('./isArrayLike'), values = require('../object/values'); /** - * Converts `value` to an array-like object if it is not one. + * Converts `value` to an array-like object if it's not one. * * @private * @param {*} value The value to process. diff --git a/internal/toObject.js b/internal/toObject.js index 1c1093409..da4a008d7 100644 --- a/internal/toObject.js +++ b/internal/toObject.js @@ -1,7 +1,7 @@ var isObject = require('../lang/isObject'); /** - * Converts `value` to an object if it is not one. + * Converts `value` to an object if it's not one. * * @private * @param {*} value The value to process. diff --git a/internal/toPath.js b/internal/toPath.js index 45314d1c4..d29f1eb52 100644 --- a/internal/toPath.js +++ b/internal/toPath.js @@ -8,7 +8,7 @@ var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*? var reEscapeChar = /\\(\\)?/g; /** - * Converts `value` to property path array if it is not one. + * Converts `value` to property path array if it's not one. * * @private * @param {*} value The value to process. diff --git a/lang.js b/lang.js index d8a7796b7..8f0a36432 100644 --- a/lang.js +++ b/lang.js @@ -1,6 +1,9 @@ module.exports = { 'clone': require('./lang/clone'), 'cloneDeep': require('./lang/cloneDeep'), + 'eq': require('./lang/eq'), + 'gt': require('./lang/gt'), + 'gte': require('./lang/gte'), 'isArguments': require('./lang/isArguments'), 'isArray': require('./lang/isArray'), 'isBoolean': require('./lang/isBoolean'), @@ -22,6 +25,8 @@ module.exports = { 'isString': require('./lang/isString'), 'isTypedArray': require('./lang/isTypedArray'), 'isUndefined': require('./lang/isUndefined'), + 'lt': require('./lang/lt'), + 'lte': require('./lang/lte'), 'toArray': require('./lang/toArray'), 'toPlainObject': require('./lang/toPlainObject') }; diff --git a/lang/clone.js b/lang/clone.js index 76f030ac9..0a972eae5 100644 --- a/lang/clone.js +++ b/lang/clone.js @@ -62,8 +62,9 @@ function clone(value, isDeep, customizer, thisArg) { customizer = isDeep; isDeep = false; } - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); - return baseClone(value, isDeep, customizer); + return typeof customizer == 'function' + ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1)) + : baseClone(value, isDeep); } module.exports = clone; diff --git a/lang/cloneDeep.js b/lang/cloneDeep.js index 4319d453c..a458141e8 100644 --- a/lang/cloneDeep.js +++ b/lang/cloneDeep.js @@ -47,8 +47,9 @@ var baseClone = require('../internal/baseClone'), * // => 20 */ function cloneDeep(value, customizer, thisArg) { - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); - return baseClone(value, true, customizer); + return typeof customizer == 'function' + ? baseClone(value, true, bindCallback(customizer, thisArg, 1)) + : baseClone(value, true); } module.exports = cloneDeep; diff --git a/lang/eq.js b/lang/eq.js new file mode 100644 index 000000000..e6a5ce0ca --- /dev/null +++ b/lang/eq.js @@ -0,0 +1 @@ +module.exports = require('./isEqual'); diff --git a/lang/gt.js b/lang/gt.js new file mode 100644 index 000000000..ddaf5ea06 --- /dev/null +++ b/lang/gt.js @@ -0,0 +1,25 @@ +/** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`. + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ +function gt(value, other) { + return value > other; +} + +module.exports = gt; diff --git a/lang/gte.js b/lang/gte.js new file mode 100644 index 000000000..4a5ffb5cd --- /dev/null +++ b/lang/gte.js @@ -0,0 +1,25 @@ +/** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`. + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ +function gte(value, other) { + return value >= other; +} + +module.exports = gte; diff --git a/lang/isArray.js b/lang/isArray.js index 36a560875..6826854c7 100644 --- a/lang/isArray.js +++ b/lang/isArray.js @@ -1,5 +1,5 @@ -var isLength = require('../internal/isLength'), - isNative = require('./isNative'), +var getNative = require('../internal/getNative'), + isLength = require('../internal/isLength'), isObjectLike = require('../internal/isObjectLike'); /** `Object#toString` result references. */ @@ -15,7 +15,7 @@ var objectProto = Object.prototype; var objToString = objectProto.toString; /* Native method references for those with the same name as other `lodash` methods. */ -var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray; +var nativeIsArray = getNative(Array, 'isArray'); /** * Checks if `value` is classified as an `Array` object. diff --git a/lang/isEqual.js b/lang/isEqual.js index 7daddb858..f2cb5d863 100644 --- a/lang/isEqual.js +++ b/lang/isEqual.js @@ -1,6 +1,5 @@ var baseIsEqual = require('../internal/baseIsEqual'), - bindCallback = require('../internal/bindCallback'), - isStrictComparable = require('../internal/isStrictComparable'); + bindCallback = require('../internal/bindCallback'); /** * Performs a deep comparison between two values to determine if they are @@ -17,6 +16,7 @@ var baseIsEqual = require('../internal/baseIsEqual'), * * @static * @memberOf _ + * @alias eq * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. @@ -46,12 +46,9 @@ var baseIsEqual = require('../internal/baseIsEqual'), * // => true */ function isEqual(value, other, customizer, thisArg) { - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); - if (!customizer && isStrictComparable(value) && isStrictComparable(other)) { - return value === other; - } + customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; var result = customizer ? customizer(value, other) : undefined; - return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; } module.exports = isEqual; diff --git a/lang/isFinite.js b/lang/isFinite.js index fc250ca1a..3a1c9059a 100644 --- a/lang/isFinite.js +++ b/lang/isFinite.js @@ -1,8 +1,8 @@ -var isNative = require('./isNative'); +var getNative = require('../internal/getNative'); /* Native method references for those with the same name as other `lodash` methods. */ var nativeIsFinite = global.isFinite, - nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite; + nativeNumIsFinite = getNative(Number, 'isFinite'); /** * Checks if `value` is a finite primitive number. diff --git a/lang/isFunction.js b/lang/isFunction.js index 44c54155b..a691ee06c 100644 --- a/lang/isFunction.js +++ b/lang/isFunction.js @@ -1,5 +1,5 @@ var baseIsFunction = require('../internal/baseIsFunction'), - isNative = require('./isNative'); + getNative = require('../internal/getNative'); /** `Object#toString` result references. */ var funcTag = '[object Function]'; @@ -14,7 +14,7 @@ var objectProto = Object.prototype; var objToString = objectProto.toString; /** Native method references. */ -var Uint8Array = isNative(Uint8Array = global.Uint8Array) && Uint8Array; +var Uint8Array = getNative(root, 'Uint8Array'); /** * Checks if `value` is classified as a `Function` object. diff --git a/lang/isMatch.js b/lang/isMatch.js index 9bc7ac174..cb48436a4 100644 --- a/lang/isMatch.js +++ b/lang/isMatch.js @@ -1,8 +1,6 @@ var baseIsMatch = require('../internal/baseIsMatch'), bindCallback = require('../internal/bindCallback'), - isStrictComparable = require('../internal/isStrictComparable'), - keys = require('../object/keys'), - toObject = require('../internal/toObject'); + getMatchData = require('../internal/getMatchData'); /** * Performs a deep comparison between `object` and `source` to determine if @@ -44,33 +42,8 @@ var baseIsMatch = require('../internal/baseIsMatch'), * // => true */ function isMatch(object, source, customizer, thisArg) { - var props = keys(source), - length = props.length; - - if (!length) { - return true; - } - if (object == null) { - return false; - } - customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); - object = toObject(object); - if (!customizer && length == 1) { - var key = props[0], - value = source[key]; - - if (isStrictComparable(value)) { - return value === object[key] && (value !== undefined || (key in object)); - } - } - var values = Array(length), - strictCompareFlags = Array(length); - - while (length--) { - value = values[length] = source[props[length]]; - strictCompareFlags[length] = isStrictComparable(value); - } - return baseIsMatch(object, props, values, strictCompareFlags, customizer); + customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); } module.exports = isMatch; diff --git a/lang/isNative.js b/lang/isNative.js index f27bb5a70..cc2de0d31 100644 --- a/lang/isNative.js +++ b/lang/isNative.js @@ -13,6 +13,9 @@ var objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; +/** 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. @@ -21,8 +24,8 @@ var objToString = objectProto.toString; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - escapeRegExp(objToString) - .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + escapeRegExp(fnToString.call(hasOwnProperty)) + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** diff --git a/lang/isObject.js b/lang/isObject.js index 63c3e95be..6db599872 100644 --- a/lang/isObject.js +++ b/lang/isObject.js @@ -22,7 +22,7 @@ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; - return type == 'function' || (!!value && type == 'object'); + return !!value && (type == 'object' || type == 'function'); } module.exports = isObject; diff --git a/lang/isPlainObject.js b/lang/isPlainObject.js index 89e0c74eb..67e0a8abd 100644 --- a/lang/isPlainObject.js +++ b/lang/isPlainObject.js @@ -1,4 +1,4 @@ -var isNative = require('./isNative'), +var getNative = require('../internal/getNative'), shimIsPlainObject = require('../internal/shimIsPlainObject'); /** `Object#toString` result references. */ @@ -14,7 +14,7 @@ var objectProto = Object.prototype; var objToString = objectProto.toString; /** Native method references. */ -var getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf; +var getPrototypeOf = getNative(Object, 'getPrototypeOf'); /** * Checks if `value` is a plain object, that is, an object created by the @@ -50,8 +50,8 @@ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && objToString.call(value) == objectTag)) { return false; } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + var valueOf = getNative(value, 'valueOf'), + objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) diff --git a/lang/lt.js b/lang/lt.js new file mode 100644 index 000000000..4439870a3 --- /dev/null +++ b/lang/lt.js @@ -0,0 +1,25 @@ +/** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`. + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ +function lt(value, other) { + return value < other; +} + +module.exports = lt; diff --git a/lang/lte.js b/lang/lte.js new file mode 100644 index 000000000..e2b8ab15a --- /dev/null +++ b/lang/lte.js @@ -0,0 +1,25 @@ +/** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`. + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ +function lte(value, other) { + return value <= other; +} + +module.exports = lte; diff --git a/math/max.js b/math/max.js index 68088410d..f95cdbc4c 100644 --- a/math/max.js +++ b/math/max.js @@ -1,5 +1,5 @@ -var arrayMax = require('../internal/arrayMax'), - createExtremum = require('../internal/createExtremum'); +var createExtremum = require('../internal/createExtremum'), + gt = require('../lang/gt'); /** * Gets the maximum value of `collection`. If `collection` is empty or falsey @@ -48,6 +48,6 @@ var arrayMax = require('../internal/arrayMax'), * _.max(users, 'age'); * // => { 'user': 'fred', 'age': 40 } */ -var max = createExtremum(arrayMax); +var max = createExtremum(gt, -Infinity); module.exports = max; diff --git a/math/min.js b/math/min.js index 4381b0a3d..1f78e8361 100644 --- a/math/min.js +++ b/math/min.js @@ -1,5 +1,5 @@ -var arrayMin = require('../internal/arrayMin'), - createExtremum = require('../internal/createExtremum'); +var createExtremum = require('../internal/createExtremum'), + lt = require('../lang/lt'); /** * Gets the minimum value of `collection`. If `collection` is empty or falsey @@ -48,6 +48,6 @@ var arrayMin = require('../internal/arrayMin'), * _.min(users, 'age'); * // => { 'user': 'barney', 'age': 36 } */ -var min = createExtremum(arrayMin, true); +var min = createExtremum(lt, Infinity); module.exports = min; diff --git a/object/get.js b/object/get.js index 7e8a3103b..0bb59b8dc 100644 --- a/object/get.js +++ b/object/get.js @@ -2,7 +2,7 @@ var baseGet = require('../internal/baseGet'), toPath = require('../internal/toPath'); /** - * Gets the property value of `path` on `object`. If the resolved value is + * Gets the property value at `path` of `object`. If the resolved value is * `undefined` the `defaultValue` is used in its place. * * @static diff --git a/object/has.js b/object/has.js index f208f8a01..f356243eb 100644 --- a/object/has.js +++ b/object/has.js @@ -1,6 +1,10 @@ var baseGet = require('../internal/baseGet'), baseSlice = require('../internal/baseSlice'), + isArguments = require('../lang/isArguments'), + isArray = require('../lang/isArray'), + isIndex = require('../internal/isIndex'), isKey = require('../internal/isKey'), + isLength = require('../internal/isLength'), last = require('../array/last'), toPath = require('../internal/toPath'); @@ -40,10 +44,14 @@ function has(object, path) { if (!result && !isKey(path)) { path = toPath(path); object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } path = last(path); - result = object != null && hasOwnProperty.call(object, path); + result = hasOwnProperty.call(object, path); } - return result; + return result || (isLength(object.length) && isIndex(path, object.length) && + (isArray(object) || isArguments(object))); } module.exports = has; diff --git a/object/keys.js b/object/keys.js index 5214c776b..a87551439 100644 --- a/object/keys.js +++ b/object/keys.js @@ -1,10 +1,10 @@ -var isArrayLike = require('../internal/isArrayLike'), - isNative = require('../lang/isNative'), +var getNative = require('../internal/getNative'), + isArrayLike = require('../internal/isArrayLike'), isObject = require('../lang/isObject'), shimKeys = require('../internal/shimKeys'); /* Native method references for those with the same name as other `lodash` methods. */ -var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; +var nativeKeys = getNative(Object, 'keys'); /** * Creates an array of the own enumerable property names of `object`. @@ -34,7 +34,7 @@ var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object != null && object.constructor; + var Ctor = object == null ? null : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); diff --git a/object/keysIn.js b/object/keysIn.js index 72a1c5e26..45a85d795 100644 --- a/object/keysIn.js +++ b/object/keysIn.js @@ -2,8 +2,7 @@ var isArguments = require('../lang/isArguments'), isArray = require('../lang/isArray'), isIndex = require('../internal/isIndex'), isLength = require('../internal/isLength'), - isObject = require('../lang/isObject'), - support = require('../support'); + isObject = require('../lang/isObject'); /** Used for native method references. */ var objectProto = Object.prototype; @@ -42,7 +41,7 @@ function keysIn(object) { } var length = object.length; length = (length && isLength(length) && - (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0; + (isArray(object) || isArguments(object)) && length) || 0; var Ctor = object.constructor, index = -1, diff --git a/object/pairs.js b/object/pairs.js index 64de3edbe..fd4644cea 100644 --- a/object/pairs.js +++ b/object/pairs.js @@ -1,4 +1,5 @@ -var keys = require('./keys'); +var keys = require('./keys'), + toObject = require('../internal/toObject'); /** * Creates a two dimensional array of the key-value pairs for `object`, @@ -15,6 +16,8 @@ var keys = require('./keys'); * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, diff --git a/object/transform.js b/object/transform.js index 4537ba1a0..9f6b8ce7e 100644 --- a/object/transform.js +++ b/object/transform.js @@ -46,7 +46,7 @@ function transform(object, iteratee, accumulator, thisArg) { if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { - accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype); + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : null); } } else { accumulator = {}; diff --git a/package.json b/package.json index 1f85a8535..c55b8aef4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "3.8.0", + "version": "3.9.0", "description": "The modern build of lodash modular utilities.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", diff --git a/string/escape.js b/string/escape.js index c4e72cc08..cd08a5ddf 100644 --- a/string/escape.js +++ b/string/escape.js @@ -13,7 +13,7 @@ var reUnescapedHtml = /[&<>"'`]/g, * use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like - * ">" and "/" don't require escaping in HTML and have no special meaning + * ">" and "/" don't need escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. diff --git a/string/pad.js b/string/pad.js index df37ded03..60b5c1332 100644 --- a/string/pad.js +++ b/string/pad.js @@ -9,7 +9,7 @@ var ceil = Math.ceil, var nativeIsFinite = global.isFinite; /** - * Pads `string` on the left and right sides if it is shorter than `length`. + * Pads `string` on the left and right sides if it's shorter than `length`. * Padding characters are truncated if they can't be evenly divided by `length`. * * @static diff --git a/string/padLeft.js b/string/padLeft.js index af5a498b2..bb0c94d0c 100644 --- a/string/padLeft.js +++ b/string/padLeft.js @@ -1,7 +1,7 @@ var createPadDir = require('../internal/createPadDir'); /** - * Pads `string` on the left side if it is shorter than `length`. Padding + * Pads `string` on the left side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static diff --git a/string/padRight.js b/string/padRight.js index e78daa5a1..dc12f5599 100644 --- a/string/padRight.js +++ b/string/padRight.js @@ -1,7 +1,7 @@ var createPadDir = require('../internal/createPadDir'); /** - * Pads `string` on the right side if it is shorter than `length`. Padding + * Pads `string` on the right side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static diff --git a/string/trunc.js b/string/trunc.js index b8e6117f2..8d9b309b9 100644 --- a/string/trunc.js +++ b/string/trunc.js @@ -11,7 +11,7 @@ var DEFAULT_TRUNC_LENGTH = 30, var reFlags = /\w*$/; /** - * Truncates `string` if it is longer than the given maximum string length. + * Truncates `string` if it's longer than the given maximum string length. * The last characters of the truncated string are replaced with the omission * string which defaults to "...". * diff --git a/support.js b/support.js index 1964a44e2..12c97f51c 100644 --- a/support.js +++ b/support.js @@ -1,11 +1,5 @@ -/** Used for native method references. */ -var objectProto = Object.prototype; - /** Used to detect DOM support. */ -var document = (document = global.window) && document.document; - -/** Native method references. */ -var propertyIsEnumerable = objectProto.propertyIsEnumerable; +var document = (document = global.window) ? document.document : null; /** * An object environment feature flags. @@ -18,31 +12,12 @@ var support = {}; (function(x) { var Ctor = function() { this.x = x; }, - args = arguments, object = { '0': x, 'length': x }, props = []; Ctor.prototype = { 'valueOf': x, 'y': x }; for (var key in new Ctor) { props.push(key); } - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but Firefox OS certified apps, older Opera mobile browsers, and - * the PlayStation 3; forced `false` for Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = /\bthis\b/.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - /** * Detect if the DOM is supported. * @@ -54,24 +29,6 @@ var support = {}; } catch(e) { support.dom = false; } - - /** - * Detect if `arguments` object indexes are non-enumerable. - * - * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object - * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat - * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` - * checks for indexes that exceed the number of function parameters and - * whose associated argument values are `0`. - * - * @memberOf _.support - * @type boolean - */ - try { - support.nonEnumArgs = !propertyIsEnumerable.call(args, 1); - } catch(e) { - support.nonEnumArgs = true; - } }(1, 0)); module.exports = support; diff --git a/utility/matchesProperty.js b/utility/matchesProperty.js index 05a7efb1c..ee268e5d6 100644 --- a/utility/matchesProperty.js +++ b/utility/matchesProperty.js @@ -13,7 +13,7 @@ var baseClone = require('../internal/baseClone'), * @memberOf _ * @category Utility * @param {Array|string} path The path of the property to get. - * @param {*} value The value to compare. + * @param {*} srcValue The value to match. * @returns {Function} Returns the new function. * @example * @@ -25,8 +25,8 @@ var baseClone = require('../internal/baseClone'), * _.find(users, _.matchesProperty('user', 'fred')); * // => { 'user': 'fred' } */ -function matchesProperty(path, value) { - return baseMatchesProperty(path, baseClone(value, true)); +function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); } module.exports = matchesProperty; diff --git a/utility/mixin.js b/utility/mixin.js index 926042b74..1340464b4 100644 --- a/utility/mixin.js +++ b/utility/mixin.js @@ -35,9 +35,6 @@ var push = arrayProto.push; * }); * } * - * // use `_.runInContext` to avoid conflicts (esp. in Node.js) - * var _ = require('lodash').runInContext(); - * * _.mixin({ 'vowels': vowels }); * _.vowels('fred'); * // => ['e'] diff --git a/utility/times.js b/utility/times.js index 28e6f0263..dba312901 100644 --- a/utility/times.js +++ b/utility/times.js @@ -8,7 +8,7 @@ var nativeIsFinite = global.isFinite, nativeMin = Math.min; /** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1; +var MAX_ARRAY_LENGTH = 4294967295; /** * Invokes the iteratee function `n` times, returning an array of the results